From patchwork Mon Sep 9 04:28:16 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Indu Bhagat X-Patchwork-Id: 1159592 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-508564-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=oracle.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="NXJBIsik"; dkim=pass (2048-bit key; unprotected) header.d=oracle.com header.i=@oracle.com header.b="g/Q3mjzP"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 46RZtJ282nz9s4Y for ; Mon, 9 Sep 2019 14:28:53 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:subject:date:message-id:in-reply-to:references; q=dns; s= default; b=fUkRcy5uhP0sxoOvgSPR3aDNLF3KOfOHCsVJkW8fpcYAivq+K4R1e 6A83wVd2dCPny53yivUqtEx5Xx6lG8/6uyGp6y9V9FLajf6JjJALYZ37PfSXwP/b ee5XoJzJg7565L9NncMsELB6HTQYzWdzzIvd3Dze+EFf1hNh3Xt+4U= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:subject:date:message-id:in-reply-to:references; s=default; bh=QbxgLXdC4xvS9gzxnOtaiwOst5g=; b=NXJBIsikuwvn6SkeY45yZNcLeBuv Qlw9BvZ2nrC5hmvMfCnZ+iYUEtxLbp1mwtRdGKilM7rO7WnqhH0QNB3mqWDxjWB8 1ehqh2MuFdi1m+8vsV5S12ErRk/JI6XgJf3O53hjfFQbb0ik8wU8vx9QFm3Wm4e0 dj2cxZlN363HMKE= Received: (qmail 108758 invoked by alias); 9 Sep 2019 04:28:44 -0000 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 Received: (qmail 108748 invoked by uid 89); 9 Sep 2019 04:28:44 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-21.2 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, SPF_HELO_PASS, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 spammy=HX-Languages-Length:1031, strncmp X-HELO: userp2130.oracle.com Received: from userp2130.oracle.com (HELO userp2130.oracle.com) (156.151.31.86) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 09 Sep 2019 04:28:43 +0000 Received: from pps.filterd (userp2130.oracle.com [127.0.0.1]) by userp2130.oracle.com (8.16.0.27/8.16.0.27) with SMTP id x894O41X004551 for ; Mon, 9 Sep 2019 04:28:41 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oracle.com; h=from : to : subject : date : message-id : in-reply-to : references; s=corp-2019-08-05; bh=m0QLAWwcwfnwwCUsQI8rKKp6x5I5dZp7GbWdzNVypL0=; b=g/Q3mjzP4Y/3BtiZOf39jBkm9WJmshhk3spGP4Ha1zRFtNGl4eUWAfGA6Y9RGb1kpCUW S79Lt2a17pTTb4Ies3msNF8ghqCK1xLNOALe1gPfley3YM3VYp/b7B9okEHquKpszWZp lccY1M/w4ir+4d0A6+bBBsNkrYtqN4jXhDmODHg5CoigI61K3ZZloQ79G4/2bJmFmgGR 5fh6TEt0aPq95eFhlu1jxJ51M7ARqVCfZCOjb+fzzTcU3gV72dndNPXf7cncQmmxrF+Y wk4Z4/38Vdk5Zv59tbGoCMzyk9qAOb1ku82yj3KFF1llQn7St+V4zCJWFFnH7nJsNaRq Jg== Received: from userp3020.oracle.com (userp3020.oracle.com [156.151.31.79]) by userp2130.oracle.com with ESMTP id 2uw1m8hhgv-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK) for ; Mon, 09 Sep 2019 04:28:41 +0000 Received: from pps.filterd (userp3020.oracle.com [127.0.0.1]) by userp3020.oracle.com (8.16.0.27/8.16.0.27) with SMTP id x894Sc9x005672 for ; Mon, 9 Sep 2019 04:28:40 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by userp3020.oracle.com with ESMTP id 2uv3wkywbw-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK) for ; Mon, 09 Sep 2019 04:28:40 +0000 Received: from abhmp0002.oracle.com (abhmp0002.oracle.com [141.146.116.8]) by aserv0121.oracle.com (8.14.4/8.13.8) with ESMTP id x894SSSs016104 for ; Mon, 9 Sep 2019 04:28:33 GMT Received: from ibhagatpc.us.oracle.com (/10.65.144.100) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Sun, 08 Sep 2019 21:28:28 -0700 From: Indu Bhagat To: gcc-patches@gcc.gnu.org Subject: [PATCH,RFC,V5 1/6] Add new function lang_GNU_GIMPLE Date: Sun, 8 Sep 2019 21:28:16 -0700 Message-Id: <1568003301-11457-2-git-send-email-indu.bhagat@oracle.com> In-Reply-To: <1568003301-11457-1-git-send-email-indu.bhagat@oracle.com> References: <1568003301-11457-1-git-send-email-indu.bhagat@oracle.com> gcc/ChangeLog: * langhooks.c (lang_GNU_GIMPLE): New Function. * langhooks.h: New Prototype. --- gcc/ChangeLog | 5 +++++ gcc/langhooks.c | 9 +++++++++ gcc/langhooks.h | 1 + 3 files changed, 15 insertions(+) diff --git a/gcc/langhooks.c b/gcc/langhooks.c index 89fb5bc..66daa9a 100644 --- a/gcc/langhooks.c +++ b/gcc/langhooks.c @@ -821,3 +821,12 @@ lang_GNU_OBJC (void) { return strncmp (lang_hooks.name, "GNU Objective-C", 15) == 0; } + +/* Returns true if the current lang_hooks represents the GNU GIMPLE + frontend. */ + +bool +lang_GNU_GIMPLE (void) +{ + return strncmp (lang_hooks.name, "GNU GIMPLE", 10) == 0; +} diff --git a/gcc/langhooks.h b/gcc/langhooks.h index a45579b..0ac794e 100644 --- a/gcc/langhooks.h +++ b/gcc/langhooks.h @@ -570,5 +570,6 @@ extern bool lang_GNU_C (void); extern bool lang_GNU_CXX (void); extern bool lang_GNU_Fortran (void); extern bool lang_GNU_OBJC (void); +extern bool lang_GNU_GIMPLE (void); #endif /* GCC_LANG_HOOKS_H */ From patchwork Mon Sep 9 04:28:17 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Indu Bhagat X-Patchwork-Id: 1159596 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-508568-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=oracle.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="Mdso1cUV"; dkim=pass (2048-bit key; unprotected) header.d=oracle.com header.i=@oracle.com header.b="PHGIB2Ve"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 46RZvV2nM9z9s4Y for ; Mon, 9 Sep 2019 14:29:58 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:subject:date:message-id:in-reply-to:references; q=dns; s= default; b=HfTpqou4sZaMvv15rsWPN4ClnpDzDmOEqK2hYPy95KpI8tZGbj87s 6sEySNxnoJ2ZNRWnUYRotZuoftR4EdS1FgxY3AZYgf5W31r1+obymiS+AigydAF9 3fmtROD93Jefx0G5mS2SLq5LA2H39IRsmk6zkb6w6x9D6IYqCwwlAY= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:subject:date:message-id:in-reply-to:references; s=default; bh=COGQUvHwueSUOvkgLXUXspICFXI=; b=Mdso1cUV1d775VAAyCo5kautsj3a MYG27T5xMePbEpw//BDTtWd9hz4VNdfCazjOe4U7cdUB6TfdG/L1lJArpGVwXeAR yBxmJw44bSi2+4U0dOHaRRU4Sq6vV8kijZB+W/vdpy81YlNubh2GN2TGTYc7LtSG ld2wd3W6sfYiwBk= Received: (qmail 110284 invoked by alias); 9 Sep 2019 04:28:56 -0000 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 Received: (qmail 110158 invoked by uid 89); 9 Sep 2019 04:28:55 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-21.6 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, SPF_HELO_PASS, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 spammy=arrange, sk:DW_AT_c, gol, sk:dw_at_c X-HELO: aserp2120.oracle.com Received: from aserp2120.oracle.com (HELO aserp2120.oracle.com) (141.146.126.78) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 09 Sep 2019 04:28:53 +0000 Received: from pps.filterd (aserp2120.oracle.com [127.0.0.1]) by aserp2120.oracle.com (8.16.0.27/8.16.0.27) with SMTP id x894NumC147095 for ; Mon, 9 Sep 2019 04:28:52 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oracle.com; h=from : to : subject : date : message-id : in-reply-to : references; s=corp-2019-08-05; bh=/YmLHuy92sUDGOoy3zGugODq6duqwOEKCHMmIixg8hg=; b=PHGIB2VesGddhvg0pJ0BUT/MIhM/oelEbtCF+PuazWsrS/EWHrRfy33/bLSoDQpEHddj AUk72moyYdVjdD4aB4otcPRP8jEhzz0ZYRJ+bA3ylQqr3GV+B4mKgCWSp36ch4N9oiNU DuZY5yILGPJlGd5GKKc3Vk4fQo+S8YGnbgdBRQhIku283EODDbYjg/cuLiMBI3CnQ4/l xodnlQtaKgdOwLEtHyB7CCNScEIglm/rW0aX+xnojCiuaTzot68igofEf1vS3AeFFus+ e0g0x5NB+FrJUMiQbM6RSc8BWgdDTb/sCs2P5/+BhhcxRlmAfw0iT9OJt3fMZVJaLla0 Ew== Received: from aserp3030.oracle.com (aserp3030.oracle.com [141.146.126.71]) by aserp2120.oracle.com with ESMTP id 2uw1jxshj2-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK) for ; Mon, 09 Sep 2019 04:28:51 +0000 Received: from pps.filterd (aserp3030.oracle.com [127.0.0.1]) by aserp3030.oracle.com (8.16.0.27/8.16.0.27) with SMTP id x894SmlC062843 for ; Mon, 9 Sep 2019 04:28:51 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by aserp3030.oracle.com with ESMTP id 2uv2ky9hjg-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK) for ; Mon, 09 Sep 2019 04:28:50 +0000 Received: from abhmp0002.oracle.com (abhmp0002.oracle.com [141.146.116.8]) by userv0121.oracle.com (8.14.4/8.13.8) with ESMTP id x894ST3e011471 for ; Mon, 9 Sep 2019 04:28:32 GMT Received: from ibhagatpc.us.oracle.com (/10.65.144.100) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Sun, 08 Sep 2019 21:28:28 -0700 From: Indu Bhagat To: gcc-patches@gcc.gnu.org Subject: [PATCH,RFC,V5 2/6] Add CTF command line options : -gtLEVEL Date: Sun, 8 Sep 2019 21:28:17 -0700 Message-Id: <1568003301-11457-3-git-send-email-indu.bhagat@oracle.com> In-Reply-To: <1568003301-11457-1-git-send-email-indu.bhagat@oracle.com> References: <1568003301-11457-1-git-send-email-indu.bhagat@oracle.com> -gtLEVEL is used to request CTF debug information and also to specify how much CTF debug information. gcc/ChangeLog: * common.opt: Add CTF debug info options. * doc/invoke.texi: Document the CTF debug info options. * flag-types.h (enum ctf_debug_info_levels): New enum. * opts.c (common_handle_option): New Function. (set_ctf_debug_level): Handle the new CTF debug info options. --- gcc/ChangeLog | 8 ++++++++ gcc/common.opt | 9 +++++++++ gcc/doc/invoke.texi | 16 ++++++++++++++++ gcc/flag-types.h | 13 +++++++++++++ gcc/opts.c | 26 ++++++++++++++++++++++++++ 5 files changed, 72 insertions(+) diff --git a/gcc/common.opt b/gcc/common.opt index f2214ed..283a959 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -125,6 +125,11 @@ enum debug_info_levels debug_info_level = DINFO_LEVEL_NONE Variable bool use_gnu_debug_info_extensions +; Level of CTF debugging information we are producing. See flag-types.h +; for the definitions of the different possible levels. +Variable +enum ctf_debug_info_levels ctf_debug_info_level = CTFINFO_LEVEL_NONE + ; Original value of maximum field alignment in bytes, specified via ; -fpack-struct=. Variable @@ -3011,6 +3016,10 @@ gcolumn-info Common Driver Var(debug_column_info,1) Init(1) Record DW_AT_decl_column and DW_AT_call_column in DWARF. +gt +Common Driver RejectNegative JoinedOrMissing +Generate CTF debug information at default level. + gdwarf Common Driver JoinedOrMissing Negative(gdwarf-) Generate debug information in default version of DWARF format. diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index bfcd76e..af42da9 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -378,6 +378,7 @@ Objective-C and Objective-C++ Dialects}. @item Debugging Options @xref{Debugging Options,,Options for Debugging Your Program}. @gccoptlist{-g -g@var{level} -gdwarf -gdwarf-@var{version} @gol +-gt -gt@var{level} @gol -ggdb -grecord-gcc-switches -gno-record-gcc-switches @gol -gstabs -gstabs+ -gstrict-dwarf -gno-strict-dwarf @gol -gas-loc-support -gno-as-loc-support @gol @@ -7823,6 +7824,21 @@ other DWARF-related options such as @option{-fno-dwarf2-cfi-asm}) retain a reference to DWARF Version 2 in their names, but apply to all currently-supported versions of DWARF. +@item -gt +@itemx -gt@var{level} +@opindex gt +Request CTF debug information and use level to specify how much CTF debug +information should be produced. If -gt is specified without a value for level, +the default level of CTF debug information is 2. + +Level 0 produces no CTF debug information at all. Thus, -gt0 negates -gt. + +Level 1 produces CTF information for tracebacks only. This includes callsite +information, but does not include type information. + +Level 2 produces type information for entities (functions, data objects etc.) +at file-scope or global-scope only. + @item -gstabs @opindex gstabs Produce debugging information in stabs format (if that is supported), diff --git a/gcc/flag-types.h b/gcc/flag-types.h index a210328..61a1432 100644 --- a/gcc/flag-types.h +++ b/gcc/flag-types.h @@ -105,6 +105,19 @@ enum dwarf_gnat_encodings Emit GNAT encodings for the rest. */ }; +/* CTF debug info levels. + CTF debug info levels are untied with DWARF debug info levels because CTF + may co-exist with DWARF. */ +enum ctf_debug_info_levels +{ + CTFINFO_LEVEL_NONE = 0, /* Write no CTF debug info. */ + CTFINFO_LEVEL_TERSE = 1, /* Write CTF information to support tracebacks + only. Not Implemented. */ + CTFINFO_LEVEL_NORMAL = 2 /* Write CTF type information for all entities + (functions, data objects, variables etc.) + at file-scope or global-scope only. */ +}; + /* Enumerate Objective-c instance variable visibility settings. */ enum ivar_visibility diff --git a/gcc/opts.c b/gcc/opts.c index 07f701c..db3711c 100644 --- a/gcc/opts.c +++ b/gcc/opts.c @@ -196,6 +196,8 @@ static void set_debug_level (enum debug_info_type type, int extended, const char *arg, struct gcc_options *opts, struct gcc_options *opts_set, location_t loc); +static void set_ctf_debug_level (const char *arg, + struct gcc_options *opts, location_t loc); static void set_fast_math_flags (struct gcc_options *opts, int set); static void decode_d_option (const char *arg, struct gcc_options *opts, location_t loc, diagnostic_context *dc); @@ -2759,6 +2761,10 @@ common_handle_option (struct gcc_options *opts, opts->x_flag_stack_usage_info = value != 0; break; + case OPT_gt: + set_ctf_debug_level (arg, opts, loc); + break; + case OPT_g: set_debug_level (NO_DEBUG, DEFAULT_GDB_EXTENSIONS, arg, opts, opts_set, loc); @@ -3088,6 +3094,26 @@ set_debug_level (enum debug_info_type type, int extended, const char *arg, } } +/* Handle a debug output -gt switch for options OPTS. */ +static void +set_ctf_debug_level (const char *arg, + struct gcc_options *opts, location_t loc) +{ + /* CTF debug flag without a level defaults to level 2. */ + if (*arg == '\0') + opts->x_ctf_debug_info_level = CTFINFO_LEVEL_NORMAL; + else + { + int argval = integral_argument (arg); + if (argval == -1) + error_at (loc, "unrecognized ctf debug output level %qs", arg); + else if (argval > CTFINFO_LEVEL_NORMAL) + error_at (loc, "ctf debug output level %qs is too high", arg); + else + opts->x_ctf_debug_info_level = (enum ctf_debug_info_levels) argval; + } +} + /* Arrange to dump core on error for diagnostic context DC. (The regular error message is still printed first, except in the case of abort ().) */ From patchwork Mon Sep 9 04:28:18 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Indu Bhagat X-Patchwork-Id: 1159594 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-508566-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=oracle.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="aFbKd13v"; dkim=pass (2048-bit key; unprotected) header.d=oracle.com header.i=@oracle.com header.b="rVZaFad2"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 46RZtt6qWbz9sCJ for ; Mon, 9 Sep 2019 14:29:26 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:subject:date:message-id:in-reply-to:references; q=dns; s= default; b=LPdtVEBRIrBr11BUMI8DedbXO4OQeOhehYWVaqSy7vi2+45DIY+Mk XDsybOlPq0Ffkrk6A4F/f6jZBXqyCPfI7Xa4Vb1wiELHFKuVXj7DcNeK4E4eD4uC SjN0dlupGMh8qaJgcypy6aXDUJ1dP1zQywRbyuMTfyFJdYjrH3W40M= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:subject:date:message-id:in-reply-to:references; s=default; bh=JxkXBSVdIFINXUieGuIaC4rG11E=; b=aFbKd13v+o6dYSjsK21BaEWQRo/l Kks2qmJ98SqW2JZUKuxyvRVZGtZ8qqUFBDe55p3w/0Y2Xi1zVKgYiA2p3+sRG09/ qC98wca3H+Z7t8dNvf/4mDk8nd654PzFSe108Lqar86xT+azVMbOLGC+TImiJ/2K 4PcBvegn1Opvis4= Received: (qmail 109545 invoked by alias); 9 Sep 2019 04:28:50 -0000 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 Received: (qmail 109432 invoked by uid 89); 9 Sep 2019 04:28:50 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-21.1 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_ASCII_DIVIDERS, KAM_SHORT, SPF_HELO_PASS, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 spammy=latter, Low, scheduled, lies X-HELO: userp2120.oracle.com Received: from userp2120.oracle.com (HELO userp2120.oracle.com) (156.151.31.85) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 09 Sep 2019 04:28:43 +0000 Received: from pps.filterd (userp2120.oracle.com [127.0.0.1]) by userp2120.oracle.com (8.16.0.27/8.16.0.27) with SMTP id x894Ne0O183537 for ; Mon, 9 Sep 2019 04:28:41 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oracle.com; h=from : to : subject : date : message-id : in-reply-to : references; s=corp-2019-08-05; bh=HZjjZLn6BzCacV8xo2gicd3D+nN7S84nhbV2P/XJh9M=; b=rVZaFad2zI4HA7B2aMNO0hdSSpbgMG26wEg1MO6nzmDJHry5CjdT5TaEwMof9qepyMLI Rbbx5k/CIFllnOvTV5khVyvwABvyT+NRwV+3lAhOF8jot6BdnwxlMuuaRwEmWc3RE9+S zi2JQx5Yp7JUdECCb5Xf9ABQoMhTO0dxNEL3fwnCOZU+tNGSfMGcE74c4SJsbDVunIWQ 1tdh72TrHqtb8zMVdnJks4ZZ0/TOLR+qKdfeqKNFlxUjt9tLm9vTpLWi8a3KmKaV05MR H63J0yu8wZqrPGURnYR1fNydRulIQspWyehM9nbqhM52KJp2Fva1CfiD6qYcI3C9Lt74 8A== Received: from userp3020.oracle.com (userp3020.oracle.com [156.151.31.79]) by userp2120.oracle.com with ESMTP id 2uw1jk1hx2-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK) for ; Mon, 09 Sep 2019 04:28:41 +0000 Received: from pps.filterd (userp3020.oracle.com [127.0.0.1]) by userp3020.oracle.com (8.16.0.27/8.16.0.27) with SMTP id x894ScIc005634 for ; Mon, 9 Sep 2019 04:28:41 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by userp3020.oracle.com with ESMTP id 2uv3wkywbk-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK) for ; Mon, 09 Sep 2019 04:28:39 +0000 Received: from abhmp0002.oracle.com (abhmp0002.oracle.com [141.146.116.8]) by aserv0122.oracle.com (8.14.4/8.14.4) with ESMTP id x894STvs028434 for ; Mon, 9 Sep 2019 04:28:32 GMT Received: from ibhagatpc.us.oracle.com (/10.65.144.100) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Sun, 08 Sep 2019 21:28:29 -0700 From: Indu Bhagat To: gcc-patches@gcc.gnu.org Subject: [PATCH,RFC,V5 3/6] Setup for CTF generation and emission Date: Sun, 8 Sep 2019 21:28:18 -0700 Message-Id: <1568003301-11457-4-git-send-email-indu.bhagat@oracle.com> In-Reply-To: <1568003301-11457-1-git-send-email-indu.bhagat@oracle.com> References: <1568003301-11457-1-git-send-email-indu.bhagat@oracle.com> Initialize CTF container when -gtLEVEL is specified. Generate CTF debug info for global decls. Import the CTF header from binutils. gcc/ChangeLog: * Makefile.in: Add ctfout.* files to GTFILES. * cgraphunit.c (symbol_table::finalize_compilation_unit): Generate CTF debug info for decl. Invoke CTF debug info emission. * ctfout.c: New file. * ctfout.h: Likewise. * gengtype.c (open_base_files): Add ctfout.h to ifiles. * passes.c (rest_of_decl_compilation): Generate CTF debug info for decl. * toplev.c (process_options): Inform the user and ignore -gtLEVEL if frontend is not C. (toplev::finalize): Finalize CTF containers. gcc/testsuite/ChangeLog: * gcc.dg/debug/ctf/ctf-1.c: New test. * gcc.dg/debug/ctf/ctf-preamble-1.c: Likewise. * gcc.dg/debug/ctf/ctf.exp: Add CTF testsuite. * gcc.dg/debug/dwarf2-ctf-1.c: New test. include/ChangeLog: * ctf.h: Import from binutils. --- gcc/ChangeLog | 14 + gcc/Makefile.in | 3 + gcc/cgraphunit.c | 12 +- gcc/ctfout.c | 175 +++++++++ gcc/ctfout.h | 53 +++ gcc/gengtype.c | 4 +- gcc/passes.c | 7 +- gcc/testsuite/ChangeLog | 7 + gcc/testsuite/gcc.dg/debug/ctf/ctf-1.c | 6 + gcc/testsuite/gcc.dg/debug/ctf/ctf-preamble-1.c | 11 + gcc/testsuite/gcc.dg/debug/ctf/ctf.exp | 41 ++ gcc/testsuite/gcc.dg/debug/dwarf2-ctf-1.c | 7 + gcc/toplev.c | 18 + include/ChangeLog | 4 + include/ctf.h | 483 ++++++++++++++++++++++++ 15 files changed, 839 insertions(+), 6 deletions(-) create mode 100644 gcc/ctfout.c create mode 100644 gcc/ctfout.h create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-1.c create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-preamble-1.c create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf.exp create mode 100644 gcc/testsuite/gcc.dg/debug/dwarf2-ctf-1.c create mode 100644 include/ctf.h diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 99d88a4..62d9256 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1256,6 +1256,7 @@ OBJS = \ cfgloopanal.o \ cfgloopmanip.o \ cfgrtl.o \ + ctfout.o \ symtab.o \ cgraph.o \ cgraphbuild.o \ @@ -2534,6 +2535,8 @@ GTFILES = $(CPPLIB_H) $(srcdir)/input.h $(srcdir)/coretypes.h \ $(srcdir)/dwarf2asm.c \ $(srcdir)/dwarf2cfi.c \ $(srcdir)/dwarf2out.c \ + $(srcdir)/ctfout.h \ + $(srcdir)/ctfout.c \ $(srcdir)/tree-vect-generic.c \ $(srcdir)/dojump.c $(srcdir)/emit-rtl.h \ $(srcdir)/emit-rtl.c $(srcdir)/except.h $(srcdir)/explow.c $(srcdir)/expr.c \ diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index cb08efe..e8130a1 100644 --- a/gcc/cgraphunit.c +++ b/gcc/cgraphunit.c @@ -205,6 +205,7 @@ along with GCC; see the file COPYING3. If not see #include "lto-section-names.h" #include "stringpool.h" #include "attribs.h" +#include "ctfout.h" /* Queue of cgraph nodes scheduled to be added into cgraph. This is a secondary queue used during optimization to accommodate passes that @@ -2851,17 +2852,22 @@ symbol_table::finalize_compilation_unit (void) if (!seen_error ()) { - /* Emit early debug for reachable functions, and by consequence, - locally scoped symbols. */ + /* Emit early debug and CTF debug info for reachable functions, and by + consequence, locally scoped symbols. */ struct cgraph_node *cnode; FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (cnode) - (*debug_hooks->early_global_decl) (cnode->decl); + { + (*debug_hooks->early_global_decl) (cnode->decl); + ctf_early_global_decl (cnode->decl); + } /* Clean up anything that needs cleaning up after initial debug generation. */ debuginfo_early_start (); (*debug_hooks->early_finish) (main_input_filename); + ctf_early_finish (main_input_filename); debuginfo_early_stop (); + } /* Finally drive the pass manager. */ diff --git a/gcc/ctfout.c b/gcc/ctfout.c new file mode 100644 index 0000000..471cf80 --- /dev/null +++ b/gcc/ctfout.c @@ -0,0 +1,175 @@ +/* Output CTF format from GCC. + Copyright (C) 2019 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "target.h" +#include "rtl.h" +#include "tree.h" +#include "memmodel.h" +#include "tm_p.h" +#include "varasm.h" +#include "output.h" +#include "dwarf2asm.h" +#include "debug.h" +#include "ctfout.h" + +/* A CTF container object - one per translation unit. */ + +static GTY (()) ctf_container_ref tu_ctfc; + +static int ctf_label_num; + +/* Pointers to various CTF sections. */ + +static GTY (()) section * ctf_info_section; + +/* Section names used to hold CTF debugging information. */ + +#ifndef CTF_INFO_SECTION_NAME +#define CTF_INFO_SECTION_NAME ".ctf" +#endif + +/* Section flags for the CTF debug info section. */ + +/* CTF debug info section. */ + +#define CTF_INFO_SECTION_FLAGS (SECTION_DEBUG) + +/* Maximum size (in bytes) of an artificially generated CTF label. */ + +#define MAX_CTF_LABEL_BYTES 40 + +static char ctf_info_section_label[MAX_CTF_LABEL_BYTES]; + +#ifndef CTF_INFO_SECTION_LABEL +#define CTF_INFO_SECTION_LABEL "Lctf" +#endif + +/* CTF container setup and teardown routines. */ + +/* Allocate a new CTF container with the desired flags. */ + +static inline ctf_container_ref +new_ctf_container (unsigned char ctp_flags) +{ + tu_ctfc = ggc_cleared_alloc (); + + tu_ctfc->ctfc_magic = CTF_MAGIC; + tu_ctfc->ctfc_version = CTF_VERSION; + tu_ctfc->ctfc_flags = ctp_flags; + + return tu_ctfc; +} + +/* Initialize a CTF container per translation unit. */ + +static void +init_ctf_containers (void) +{ + tu_ctfc = new_ctf_container (0); +} + +/* Delete the CTF container's resources. */ + +static void +delete_ctf_container (ctf_container_ref ctfc) +{ + /* FIXME - CTF container can be cleaned up now. + Will the ggc machinery take care of cleaning up the container structure + including the hash_map members etc. ? */ + if (ctfc) + { + ctfc = NULL; + } +} + +/* Initialize the various sections and labels for CTF output. */ + +void +init_ctf_sections (void) +{ + ctf_info_section = get_section (CTF_INFO_SECTION_NAME, + CTF_INFO_SECTION_FLAGS, + NULL); + ASM_GENERATE_INTERNAL_LABEL (ctf_info_section_label, + CTF_INFO_SECTION_LABEL, ctf_label_num++); +} + +/* Asm'out the CTF preamble. */ + +static void +ctf_asm_preamble (ctf_container_ref ctfc) +{ + dw2_asm_output_data (2, ctfc->ctfc_magic, + "CTF preamble magic number"); + dw2_asm_output_data (1, ctfc->ctfc_version, "CTF preamble version"); + dw2_asm_output_data (1, ctfc->ctfc_flags, "CTF preamble flags"); +} + +/* Output the CTF header. */ + +static void +output_ctf_header (ctf_container_ref ctfc) +{ + switch_to_section (ctf_info_section); + ASM_OUTPUT_LABEL (asm_out_file, ctf_info_section_label); + + ctf_asm_preamble (ctfc); +} + +/* CTF routines interfacing to the compiler. */ + +void +ctf_debug_init (void) +{ + init_ctf_containers (); +} + +void +ctf_early_finish (const char * ARG_UNUSED (filename)) +{ + if (ctf_debug_info_level == CTFINFO_LEVEL_NONE) + return; + + init_ctf_sections (); + + output_ctf_header (tu_ctfc); +} + +void +ctf_early_global_decl (tree ARG_UNUSED (decl)) +{ + /* Generate CTF type information if appropriate debug level is set + (ctf_debug_info_level == CTFINFO_LEVEL_NORMAL). */ +} + +/* Reset all state within ctfout.c so that we can rerun the compiler + within the same process. For use by toplev::finalize. */ + +void +ctfout_c_finalize (void) +{ + ctf_info_section = NULL; + + delete_ctf_container (tu_ctfc); +} + +#include "gt-ctfout.h" diff --git a/gcc/ctfout.h b/gcc/ctfout.h new file mode 100644 index 0000000..f281aaf --- /dev/null +++ b/gcc/ctfout.h @@ -0,0 +1,53 @@ +/* ctfout.h - Various declarations for functions found in ctfout.c + Copyright (C) 2019 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +. */ + +/* This file defines all data structures used by the compiler to generate + CTF types. These are compiler internal representations and closely + reflect the CTF format requirements in . */ + +#ifndef GCC_CTFOUT_H +#define GCC_CTFOUT_H 1 + +#include "ctf.h" + +/* CTF container structure. + It is the context passed around when generating CTF debug info. There is + one container per translation unit. */ + +typedef struct GTY (()) ctf_container +{ + /* CTF Preamble. */ + unsigned short ctfc_magic; + unsigned char ctfc_version; + unsigned char ctfc_flags; + /* CTF Types. */ + // hash_map * GTY (()) ctfc_types; +} ctf_container_t; + +typedef ctf_container_t * ctf_container_ref; + +void ctf_debug_init (void); + +void ctf_early_global_decl (tree decl); + +void ctf_early_finish (const char * filename); + +void ctfout_c_finalize (void); + +#endif /* GCC_CTFOUT_H */ diff --git a/gcc/gengtype.c b/gcc/gengtype.c index 5331733..39de737 100644 --- a/gcc/gengtype.c +++ b/gcc/gengtype.c @@ -1724,8 +1724,8 @@ open_base_files (void) "tree-dfa.h", "tree-ssa.h", "reload.h", "cpplib.h", "tree-chrec.h", "except.h", "output.h", "cfgloop.h", "target.h", "lto-streamer.h", "target-globals.h", "ipa-ref.h", "cgraph.h", "symbol-summary.h", - "ipa-prop.h", "ipa-fnsummary.h", "dwarf2out.h", "omp-general.h", - "omp-offload.h", NULL + "ipa-prop.h", "ipa-fnsummary.h", "dwarf2out.h", "ctfout.h", + "omp-general.h", "omp-offload.h", NULL }; const char *const *ifp; outf_p gtype_desc_c; diff --git a/gcc/passes.c b/gcc/passes.c index f715c67..93ebef4 100644 --- a/gcc/passes.c +++ b/gcc/passes.c @@ -63,6 +63,7 @@ along with GCC; see the file COPYING3. If not see #include "diagnostic-core.h" /* for fnotice */ #include "stringpool.h" #include "attribs.h" +#include "ctfout.h" using namespace gcc; @@ -322,7 +323,11 @@ rest_of_decl_compilation (tree decl, /* Avoid confusing the debug information machinery when there are errors. */ && !seen_error ()) - (*debug_hooks->early_global_decl) (decl); + { + (*debug_hooks->early_global_decl) (decl); + /* Generate CTF debug info. */ + ctf_early_global_decl (decl); + } } /* Called after finishing a record, union or enumeral type. */ diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-1.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-1.c new file mode 100644 index 0000000..1be0dfb --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-1.c @@ -0,0 +1,6 @@ +/* { dg-do compile } */ +/* { dg-options "-gt" } */ + +void func(void) +{ +} diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-preamble-1.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-preamble-1.c new file mode 100644 index 0000000..476ca80 --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-preamble-1.c @@ -0,0 +1,11 @@ +/* Verify the CTF preamble in the CTF section. */ + +/* { dg-do compile ) */ +/* { dg-options "-O0 -gt -dA" } */ +/* { dg-final { scan-assembler "0xdff2.*CTF preamble magic number" } } */ +/* { dg-final { scan-assembler "0x4.*CTF preamble version" } } */ +/* { dg-final { scan-assembler "0.*CTF preamble flags" } } */ + +void func (void) +{ +} diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf.exp b/gcc/testsuite/gcc.dg/debug/ctf/ctf.exp new file mode 100644 index 0000000..46055f8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf.exp @@ -0,0 +1,41 @@ +# Copyright (C) 2002-2019 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GCC; see the file COPYING3. If not see +# . + +# GCC testsuite that uses the `dg.exp' driver. + +# Load support procs. +load_lib gcc-dg.exp + +# Disable on ptx (in sync with DWARF testsuite) +if { [istarget nvptx-*-*] } { + return +} + +# If a testcase doesn't have special options, use these. +global DEFAULT_CFLAGS +if ![info exists DEFAULT_CFLAGS] then { + set DEFAULT_CFLAGS " -ansi -pedantic-errors" +} + +# Initialize `dg'. +dg-init + +# Main loop. +dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cS\] ]] \ + "" $DEFAULT_CFLAGS + +# All done. +dg-finish diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2-ctf-1.c b/gcc/testsuite/gcc.dg/debug/dwarf2-ctf-1.c new file mode 100644 index 0000000..4ffa8ee --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/dwarf2-ctf-1.c @@ -0,0 +1,7 @@ +/* Verify that CTF debug info can co-exist with other debug formats. */ +/* { dg-do compile } */ +/* { dg-options "-gt -dA" } */ +/* { dg-final { scan-assembler "0xdff2.*CTF preamble magic number" } } */ + +void func (void) +{ } diff --git a/gcc/toplev.c b/gcc/toplev.c index d741a66..4422508 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -72,6 +72,7 @@ along with GCC; see the file COPYING3. If not see #include "pass_manager.h" #include "auto-profile.h" #include "dwarf2out.h" +#include "ctfout.h" #include "ipa-reference.h" #include "symbol-summary.h" #include "tree-vrp.h" @@ -1293,6 +1294,8 @@ parse_alignment_opts (void) static void process_options (void) { + const char *language_string = lang_hooks.name; + /* Just in case lang_hooks.post_options ends up calling a debug_hook. This can happen with incorrect pre-processed input. */ debug_hooks = &do_nothing_debug_hooks; @@ -1465,6 +1468,17 @@ process_options (void) debug_info_level = DINFO_LEVEL_NONE; } + /* CTF is supported for only C at this time. + Compiling with -flto results in frontend language of GNU GIMPLE. */ + if (!lang_GNU_C () && !lang_GNU_GIMPLE () + && ctf_debug_info_level > CTFINFO_LEVEL_NONE) + { + inform (UNKNOWN_LOCATION, + "CTF debug info requested, but not supported for %qs frontend", + language_string); + ctf_debug_info_level = CTFINFO_LEVEL_NONE; + } + if (flag_dump_final_insns && !flag_syntax_only && !no_backend) { FILE *final_output = fopen (flag_dump_final_insns, "w"); @@ -1537,6 +1551,9 @@ process_options (void) flag_var_tracking_uninit = 0; } + if (ctf_debug_info_level > CTFINFO_LEVEL_NONE) + ctf_debug_init (); + /* The debug hooks are used to implement -fdump-go-spec because it gives a simple and stable API for all the information we need to dump. */ @@ -2348,6 +2365,7 @@ toplev::finalize (void) cgraph_c_finalize (); cgraphunit_c_finalize (); dwarf2out_c_finalize (); + ctfout_c_finalize (); gcse_c_finalize (); ipa_cp_c_finalize (); ira_costs_c_finalize (); diff --git a/include/ctf.h b/include/ctf.h new file mode 100644 index 0000000..3a6f266 --- /dev/null +++ b/include/ctf.h @@ -0,0 +1,483 @@ +/* CTF format description. + Copyright (C) 2019 Free Software Foundation, Inc. + + This file is part of libctf. + + libctf is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation; either version 3, or (at your option) any later + version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not see + . */ + +#ifndef _CTF_H +#define _CTF_H + +#include +#include +#include + + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* CTF - Compact ANSI-C Type Format + + This file format can be used to compactly represent the information needed + by a debugger to interpret the ANSI-C types used by a given program. + Traditionally, this kind of information is generated by the compiler when + invoked with the -g flag and is stored in "stabs" strings or in the more + modern DWARF format. CTF provides a representation of only the information + that is relevant to debugging a complex, optimized C program such as the + operating system kernel in a form that is significantly more compact than + the equivalent stabs or DWARF representation. The format is data-model + independent, so consumers do not need different code depending on whether + they are 32-bit or 64-bit programs; libctf automatically compensates for + endianness variations. CTF assumes that a standard ELF symbol table is + available for use in the debugger, and uses the structure and data of the + symbol table to avoid storing redundant information. The CTF data may be + compressed on disk or in memory, indicated by a bit in the header. CTF may + be interpreted in a raw disk file, or it may be stored in an ELF section, + typically named .ctf. Data structures are aligned so that a raw CTF file or + CTF ELF section may be manipulated using mmap(2). + + The CTF file or section itself has the following structure: + + +--------+--------+---------+----------+----------+-------+--------+ + | file | type | data | function | variable | data | string | + | header | labels | objects | info | info | types | table | + +--------+--------+---------+----------+----------+-------+--------+ + + The file header stores a magic number and version information, encoding + flags, and the byte offset of each of the sections relative to the end of the + header itself. If the CTF data has been uniquified against another set of + CTF data, a reference to that data also appears in the the header. This + reference is the name of the label corresponding to the types uniquified + against. + + Following the header is a list of labels, used to group the types included in + the data types section. Each label is accompanied by a type ID i. A given + label refers to the group of types whose IDs are in the range [0, i]. + + Data object and function records are stored in the same order as they appear + in the corresponding symbol table, except that symbols marked SHN_UNDEF are + not stored and symbols that have no type data are padded out with zeroes. + For each data object, the type ID (a small integer) is recorded. For each + function, the type ID of the return type and argument types is recorded. + + Variable records (as distinct from data objects) provide a modicum of support + for non-ELF systems, mapping a variable name to a CTF type ID. The variable + names are sorted into ASCIIbetical order, permitting binary searching. + + The data types section is a list of variable size records that represent each + type, in order by their ID. The types themselves form a directed graph, + where each node may contain one or more outgoing edges to other type nodes, + denoted by their ID. + + Strings are recorded as a string table ID (0 or 1) and a byte offset into the + string table. String table 0 is the internal CTF string table. String table + 1 is the external string table, which is the string table associated with the + ELF symbol table for this object. CTF does not record any strings that are + already in the symbol table, and the CTF string table does not contain any + duplicated strings. + + If the CTF data has been merged with another parent CTF object, some outgoing + edges may refer to type nodes that exist in another CTF object. The debugger + and libctf library are responsible for connecting the appropriate objects + together so that the full set of types can be explored and manipulated. + + This connection is done purely using the ctf_import() function. There is no + notation anywhere in the child CTF file indicating which parent it is + connected to: it is the debugger's responsibility to track this. */ + +#define CTF_MAX_TYPE 0xfffffffe /* Max type identifier value. */ +#define CTF_MAX_PTYPE 0x7fffffff /* Max parent type identifier value. */ +#define CTF_MAX_NAME 0x7fffffff /* Max offset into a string table. */ +#define CTF_MAX_VLEN 0xffffff /* Max struct, union, enum members or args. */ + +/* See ctf_type_t */ +#define CTF_MAX_SIZE 0xfffffffe /* Max size of a v2 type in bytes. */ +#define CTF_LSIZE_SENT 0xffffffff /* Sentinel for v2 ctt_size. */ + + /* Start of actual data structure definitions. + + Every field in these structures must have corresponding code in the + endianness-swapping machinery in libctf/ctf-open.c. */ + +typedef struct ctf_preamble +{ + unsigned short ctp_magic; /* Magic number (CTF_MAGIC). */ + unsigned char ctp_version; /* Data format version number (CTF_VERSION). */ + unsigned char ctp_flags; /* Flags (see below). */ +} ctf_preamble_t; + +typedef struct ctf_header +{ + ctf_preamble_t cth_preamble; + uint32_t cth_parlabel; /* Ref to name of parent lbl uniq'd against. */ + uint32_t cth_parname; /* Ref to basename of parent. */ + uint32_t cth_lbloff; /* Offset of label section. */ + uint32_t cth_objtoff; /* Offset of object section. */ + uint32_t cth_funcoff; /* Offset of function section. */ + uint32_t cth_varoff; /* Offset of variable section. */ + uint32_t cth_typeoff; /* Offset of type section. */ + uint32_t cth_stroff; /* Offset of string section. */ + uint32_t cth_strlen; /* Length of string section in bytes. */ +} ctf_header_t; + +#define cth_magic cth_preamble.ctp_magic +#define cth_version cth_preamble.ctp_version +#define cth_flags cth_preamble.ctp_flags + +#define CTF_MAGIC 0xdff2 /* Magic number identifying header. */ + +/* Data format version number. */ + +/* v1 upgraded to v2 is not quite the same as native v2 (the boundary between + parent and child types is different), and you can write it out again via + ctf_compress_write(), so we must track whether the thing was originally v1 or + not. If we were writing the header from scratch, we would add a *pair* of + version number fields to allow for this, but this will do for now. (A flag + will not do, because we need to encode both the version we came from and the + version we went to, not just "we were upgraded".) */ + +# define CTF_VERSION_1 1 +# define CTF_VERSION_1_UPGRADED_3 2 +# define CTF_VERSION_2 3 + +#define CTF_VERSION_3 4 +#define CTF_VERSION CTF_VERSION_3 /* Current version. */ + +#define CTF_F_COMPRESS 0x1 /* Data buffer is compressed by libctf. */ + +typedef struct ctf_lblent +{ + uint32_t ctl_label; /* Ref to name of label. */ + uint32_t ctl_type; /* Last type associated with this label. */ +} ctf_lblent_t; + +typedef struct ctf_varent +{ + uint32_t ctv_name; /* Reference to name in string table. */ + uint32_t ctv_type; /* Index of type of this variable. */ +} ctf_varent_t; + +/* In format v2, type sizes, measured in bytes, come in two flavours. Nearly + all of them fit into a (UINT_MAX - 1), and thus can be stored in the ctt_size + member of a ctf_stype_t. The maximum value for these sizes is CTF_MAX_SIZE. + Types larger than this must be stored in the ctf_lsize member of a + ctf_type_t. Use of this member is indicated by the presence of + CTF_LSIZE_SENT in ctt_size. */ + +typedef struct ctf_stype +{ + uint32_t ctt_name; /* Reference to name in string table. */ + uint32_t ctt_info; /* Encoded kind, variant length (see below). */ +#ifndef __GNUC__ + union + { + uint32_t _size; /* Size of entire type in bytes. */ + uint32_t _type; /* Reference to another type. */ + } _u; +#else + __extension__ + union + { + uint32_t ctt_size; /* Size of entire type in bytes. */ + uint32_t ctt_type; /* Reference to another type. */ + }; +#endif +} ctf_stype_t; + +typedef struct ctf_type +{ + uint32_t ctt_name; /* Reference to name in string table. */ + uint32_t ctt_info; /* Encoded kind, variant length (see below). */ +#ifndef __GNUC__ +union + { + uint32_t _size; /* Always CTF_LSIZE_SENT. */ + uint32_t _type; /* Do not use. */ + } _u; +#else + __extension__ + union + { + uint32_t ctt_size; /* Always CTF_LSIZE_SENT. */ + uint32_t ctt_type; /* Do not use. */ + }; +#endif + uint32_t ctt_lsizehi; /* High 32 bits of type size in bytes. */ + uint32_t ctt_lsizelo; /* Low 32 bits of type size in bytes. */ +} ctf_type_t; + +#ifndef __GNUC__ +#define ctt_size _u._size /* For fundamental types that have a size. */ +#define ctt_type _u._type /* For types that reference another type. */ +#endif + +/* The following macros and inline functions compose and decompose values for + ctt_info and ctt_name, as well as other structures that contain name + references. Use outside libdtrace-ctf itself is explicitly for access to CTF + files directly: types returned from the library will always appear to be + CTF_V2. + + v1: (transparently upgraded to v2 at open time: may be compiled out of the + library) + ------------------------ + ctt_info: | kind | isroot | vlen | + ------------------------ + 15 11 10 9 0 + + v2: + ------------------------ + ctt_info: | kind | isroot | vlen | + ------------------------ + 31 26 25 24 0 + + CTF_V1 and V2 _INFO_VLEN have the same interface: + + kind = CTF_*_INFO_KIND(c.ctt_info); <-- CTF_K_* value (see below) + vlen = CTF_*_INFO_VLEN(fp, c.ctt_info); <-- length of variable data list + + stid = CTF_NAME_STID(c.ctt_name); <-- string table id number (0 or 1) + offset = CTF_NAME_OFFSET(c.ctt_name); <-- string table byte offset + + c.ctt_info = CTF_TYPE_INFO(kind, vlen); + c.ctt_name = CTF_TYPE_NAME(stid, offset); */ + +# define CTF_V1_INFO_KIND(info) (((info) & 0xf800) >> 11) +# define CTF_V1_INFO_ISROOT(info) (((info) & 0x0400) >> 10) +# define CTF_V1_INFO_VLEN(info) (((info) & CTF_MAX_VLEN_V1)) + +#define CTF_V2_INFO_KIND(info) (((info) & 0xfc000000) >> 26) +#define CTF_V2_INFO_ISROOT(info) (((info) & 0x2000000) >> 25) +#define CTF_V2_INFO_VLEN(info) (((info) & CTF_MAX_VLEN)) + +#define CTF_NAME_STID(name) ((name) >> 31) +#define CTF_NAME_OFFSET(name) ((name) & CTF_MAX_NAME) + +/* V2 only. */ +#define CTF_TYPE_INFO(kind, isroot, vlen) \ + (((kind) << 26) | (((isroot) ? 1 : 0) << 25) | ((vlen) & CTF_MAX_VLEN)) + +#define CTF_TYPE_NAME(stid, offset) \ + (((stid) << 31) | ((offset) & CTF_MAX_NAME)) + +/* The next set of macros are for public consumption only. Not used internally, + since the relevant type boundary is dependent upon the version of the file at + *opening* time, not the version after transparent upgrade. Use + ctf_type_isparent() / ctf_type_ischild() for that. */ + +#define CTF_V2_TYPE_ISPARENT(fp, id) ((id) <= CTF_MAX_PTYPE) +#define CTF_V2_TYPE_ISCHILD(fp, id) ((id) > CTF_MAX_PTYPE) +#define CTF_V2_TYPE_TO_INDEX(id) ((id) & CTF_MAX_PTYPE) +#define CTF_V2_INDEX_TO_TYPE(id, child) ((child) ? ((id) | (CTF_MAX_PTYPE+1)) : (id)) + +# define CTF_V1_TYPE_ISPARENT(fp, id) ((id) <= CTF_MAX_PTYPE_V1) +# define CTF_V1_TYPE_ISCHILD(fp, id) ((id) > CTF_MAX_PTYPE_V1) +# define CTF_V1_TYPE_TO_INDEX(id) ((id) & CTF_MAX_PTYPE_V1) +# define CTF_V1_INDEX_TO_TYPE(id, child) ((child) ? ((id) | (CTF_MAX_PTYPE_V1+1)) : (id)) + +/* Valid for both V1 and V2. */ +#define CTF_TYPE_LSIZE(cttp) \ + (((uint64_t)(cttp)->ctt_lsizehi) << 32 | (cttp)->ctt_lsizelo) +#define CTF_SIZE_TO_LSIZE_HI(size) ((uint32_t)((uint64_t)(size) >> 32)) +#define CTF_SIZE_TO_LSIZE_LO(size) ((uint32_t)(size)) + +#define CTF_STRTAB_0 0 /* String table id 0 (in-CTF). */ +#define CTF_STRTAB_1 1 /* String table id 1 (ELF strtab). */ + +/* Values for CTF_TYPE_KIND(). If the kind has an associated data list, + CTF_INFO_VLEN() will extract the number of elements in the list, and + the type of each element is shown in the comments below. */ + +#define CTF_K_UNKNOWN 0 /* Unknown type (used for padding). */ +#define CTF_K_INTEGER 1 /* Variant data is CTF_INT_DATA (see below). */ +#define CTF_K_FLOAT 2 /* Variant data is CTF_FP_DATA (see below). */ +#define CTF_K_POINTER 3 /* ctt_type is referenced type. */ +#define CTF_K_ARRAY 4 /* Variant data is single ctf_array_t. */ +#define CTF_K_FUNCTION 5 /* ctt_type is return type, variant data is + list of argument types (unsigned short's for v1, + uint32_t's for v2). */ +#define CTF_K_STRUCT 6 /* Variant data is list of ctf_member_t's. */ +#define CTF_K_UNION 7 /* Variant data is list of ctf_member_t's. */ +#define CTF_K_ENUM 8 /* Variant data is list of ctf_enum_t's. */ +#define CTF_K_FORWARD 9 /* No additional data; ctt_name is tag. */ +#define CTF_K_TYPEDEF 10 /* ctt_type is referenced type. */ +#define CTF_K_VOLATILE 11 /* ctt_type is base type. */ +#define CTF_K_CONST 12 /* ctt_type is base type. */ +#define CTF_K_RESTRICT 13 /* ctt_type is base type. */ +#define CTF_K_SLICE 14 /* Variant data is a ctf_slice_t. */ + +#define CTF_K_MAX 63 /* Maximum possible (V2) CTF_K_* value. */ + +/* Values for ctt_type when kind is CTF_K_INTEGER. The flags, offset in bits, + and size in bits are encoded as a single word using the following macros. + (However, you can also encode the offset and bitness in a slice.) */ + +#define CTF_INT_ENCODING(data) (((data) & 0xff000000) >> 24) +#define CTF_INT_OFFSET(data) (((data) & 0x00ff0000) >> 16) +#define CTF_INT_BITS(data) (((data) & 0x0000ffff)) + +#define CTF_INT_DATA(encoding, offset, bits) \ + (((encoding) << 24) | ((offset) << 16) | (bits)) + +#define CTF_INT_SIGNED 0x01 /* Integer is signed (otherwise unsigned). */ +#define CTF_INT_CHAR 0x02 /* Character display format. */ +#define CTF_INT_BOOL 0x04 /* Boolean display format. */ +#define CTF_INT_VARARGS 0x08 /* Varargs display format. */ + +/* Use CTF_CHAR to produce a char that agrees with the system's native + char signedness. */ +#if CHAR_MIN == 0 +# define CTF_CHAR (CTF_INT_CHAR) +#else +# define CTF_CHAR (CTF_INT_CHAR | CTF_INT_SIGNED) +#endif + +/* Values for ctt_type when kind is CTF_K_FLOAT. The encoding, offset in bits, + and size in bits are encoded as a single word using the following macros. + (However, you can also encode the offset and bitness in a slice.) */ + +#define CTF_FP_ENCODING(data) (((data) & 0xff000000) >> 24) +#define CTF_FP_OFFSET(data) (((data) & 0x00ff0000) >> 16) +#define CTF_FP_BITS(data) (((data) & 0x0000ffff)) + +#define CTF_FP_DATA(encoding, offset, bits) \ + (((encoding) << 24) | ((offset) << 16) | (bits)) + +/* Variant data when kind is CTF_K_FLOAT is an encoding in the top eight bits. */ +#define CTF_FP_ENCODING(data) (((data) & 0xff000000) >> 24) + +#define CTF_FP_SINGLE 1 /* IEEE 32-bit float encoding. */ +#define CTF_FP_DOUBLE 2 /* IEEE 64-bit float encoding. */ +#define CTF_FP_CPLX 3 /* Complex encoding. */ +#define CTF_FP_DCPLX 4 /* Double complex encoding. */ +#define CTF_FP_LDCPLX 5 /* Long double complex encoding. */ +#define CTF_FP_LDOUBLE 6 /* Long double encoding. */ +#define CTF_FP_INTRVL 7 /* Interval (2x32-bit) encoding. */ +#define CTF_FP_DINTRVL 8 /* Double interval (2x64-bit) encoding. */ +#define CTF_FP_LDINTRVL 9 /* Long double interval (2x128-bit) encoding. */ +#define CTF_FP_IMAGRY 10 /* Imaginary (32-bit) encoding. */ +#define CTF_FP_DIMAGRY 11 /* Long imaginary (64-bit) encoding. */ +#define CTF_FP_LDIMAGRY 12 /* Long double imaginary (128-bit) encoding. */ + +#define CTF_FP_MAX 12 /* Maximum possible CTF_FP_* value */ + +/* A slice increases the offset and reduces the bitness of the referenced + ctt_type, which must be a type which has an encoding (fp, int, or enum). We + also store the referenced type in here, because it is easier to keep the + ctt_size correct for the slice than to shuffle the size into here and keep + the ctt_type where it is for other types. */ + +typedef struct ctf_slice +{ + uint32_t cts_type; + unsigned char cts_offset; + unsigned char cts_bits; +} ctf_slice_t; + +typedef struct ctf_array +{ + uint32_t cta_contents; /* Reference to type of array contents. */ + uint32_t cta_index; /* Reference to type of array index. */ + uint32_t cta_nelems; /* Number of elements. */ +} ctf_array_t; + +/* Most structure members have bit offsets that can be expressed using a short. + Some don't. ctf_member_t is used for structs which cannot contain any of + these large offsets, whereas ctf_lmember_t is used in the latter case. If + any member of a given struct has an offset that cannot be expressed using a + uint32_t, all members will be stored as type ctf_lmember_t. This is expected + to be very rare (but nonetheless possible). */ + +#define CTF_LSTRUCT_THRESH 536870912 + +typedef struct ctf_member_v2 +{ + uint32_t ctm_name; /* Reference to name in string table. */ + uint32_t ctm_offset; /* Offset of this member in bits. */ + uint32_t ctm_type; /* Reference to type of member. */ +} ctf_member_t; + +typedef struct ctf_lmember_v2 +{ + uint32_t ctlm_name; /* Reference to name in string table. */ + uint32_t ctlm_offsethi; /* High 32 bits of member offset in bits. */ + uint32_t ctlm_type; /* Reference to type of member. */ + uint32_t ctlm_offsetlo; /* Low 32 bits of member offset in bits. */ +} ctf_lmember_t; + +#define CTF_LMEM_OFFSET(ctlmp) \ + (((uint64_t)(ctlmp)->ctlm_offsethi) << 32 | (ctlmp)->ctlm_offsetlo) +#define CTF_OFFSET_TO_LMEMHI(offset) ((uint32_t)((uint64_t)(offset) >> 32)) +#define CTF_OFFSET_TO_LMEMLO(offset) ((uint32_t)(offset)) + +typedef struct ctf_enum +{ + uint32_t cte_name; /* Reference to name in string table. */ + int32_t cte_value; /* Value associated with this name. */ +} ctf_enum_t; + +/* The ctf_archive is a collection of ctf_file_t's stored together. The format + is suitable for mmap()ing: this control structure merely describes the + mmap()ed archive (and overlaps the first few bytes of it), hence the + greater care taken with integral types. All CTF files in an archive + must have the same data model. (This is not validated.) + + All integers in this structure are stored in little-endian byte order. + + The code relies on the fact that everything in this header is a uint64_t + and thus the header needs no padding (in particular, that no padding is + needed between ctfa_ctfs and the unnamed ctfa_archive_modent array + that follows it). + + This is *not* the same as the data structure returned by the ctf_arc_*() + functions: this is the low-level on-disk representation. */ + +#define CTFA_MAGIC 0x8b47f2a4d7623eeb /* Random. */ +struct ctf_archive +{ + /* Magic number. (In loaded files, overwritten with the file size + so ctf_arc_close() knows how much to munmap()). */ + uint64_t ctfa_magic; + + /* CTF data model. */ + uint64_t ctfa_model; + + /* Number of CTF files in the archive. */ + uint64_t ctfa_nfiles; + + /* Offset of the name table. */ + uint64_t ctfa_names; + + /* Offset of the CTF table. Each element starts with a size (a uint64_t + in network byte order) then a ctf_file_t of that size. */ + uint64_t ctfa_ctfs; +}; + +/* An array of ctfa_nnamed of this structure lies at + ctf_archive[ctf_archive->ctfa_modents] and gives the ctfa_ctfs or + ctfa_names-relative offsets of each name or ctf_file_t. */ + +typedef struct ctf_archive_modent +{ + uint64_t name_offset; + uint64_t ctf_offset; +} ctf_archive_modent_t; + +#ifdef __cplusplus +} +#endif + +#endif /* _CTF_H */ From patchwork Mon Sep 9 04:28:19 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Indu Bhagat X-Patchwork-Id: 1159598 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-508570-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=oracle.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="Fbf3v9hp"; dkim=pass (2048-bit key; unprotected) header.d=oracle.com header.i=@oracle.com header.b="NoOmMil0"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 46RZw475l9z9s4Y for ; Mon, 9 Sep 2019 14:30:28 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:subject:date:message-id:in-reply-to:references; q=dns; s= default; b=c37fhe/pMo7XeoTwJ19AhVtXLaJEDnopo0XqGOzFXxValBDrjGF85 ST7jWQLLiKSfiqTU4pmtyvsyBCfV1CvZMk4qrVv8GcW9KYi29YioTKBSiwoJ1tta xYfAdydAkWQbB8NmYALZhx4FrnxpVX4BmFdNUcYUL2FgYK1cWPo84k= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:subject:date:message-id:in-reply-to:references; s=default; bh=VS0C1btG4CQgVv56wEsjfwdr2Tc=; b=Fbf3v9hpbfRxzkOn1oDM2Ea45gtU maiQzruok1Wh8BHnDBx3vfEmGbONZ+i+7vgLI0+OjD0S1XheLeeKVWTBlUM1Snjl eDDmfDy9wxEgT+0LkRNWPOTjSVAD8M3ippWfQGwkScBoRK7zlXHIVNHabAo4T3EZ WoCYXljGymodFjI= Received: (qmail 111961 invoked by alias); 9 Sep 2019 04:29:16 -0000 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 Received: (qmail 111847 invoked by uid 89); 9 Sep 2019 04:29:15 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-21.8 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_SHORT, SPF_HELO_PASS, SPF_PASS, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 spammy=dies, Head, associate, Base X-HELO: userp2120.oracle.com Received: from userp2120.oracle.com (HELO userp2120.oracle.com) (156.151.31.85) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 09 Sep 2019 04:28:54 +0000 Received: from pps.filterd (userp2120.oracle.com [127.0.0.1]) by userp2120.oracle.com (8.16.0.27/8.16.0.27) with SMTP id x894NbM3183530 for ; Mon, 9 Sep 2019 04:28:52 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oracle.com; h=from : to : subject : date : message-id : in-reply-to : references; s=corp-2019-08-05; bh=76NJStSejRsrKflLuvvOIBQePAYHh194yXP4ZTNj0Q0=; b=NoOmMil08r1IdpCnRW8MZ+XbL4YNSrz1s/i0ELdjFjQvcwpaFI8D1xVhlvgp+OKhCLgZ D3w+4aYpI3EzRRVGoFK7hfubsSy8BilwaZ4knyCOWMnn9/ouDLNt6veCTl/0SSuJgLIs /zuD+eFf4+KJgBvGsQS/wOxuhsDS0g40QArtFJfgXKdUwVtYG3QyLOjQJdzMY4XDpoyV rrYhvB4uyTcg+uxoYajBTk23jMeqC03jVf1p7qCqp17bdE0En1hHQCiWHM8oR090MAii PM4l7hmXoA8l/VeLgvxt/PNLKG8XdVvGsAzDaNzgEgLitCWZKbGgPaY5LAiMSziTMVOV YQ== Received: from aserp3030.oracle.com (aserp3030.oracle.com [141.146.126.71]) by userp2120.oracle.com with ESMTP id 2uw1jk1hy7-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK) for ; Mon, 09 Sep 2019 04:28:52 +0000 Received: from pps.filterd (aserp3030.oracle.com [127.0.0.1]) by aserp3030.oracle.com (8.16.0.27/8.16.0.27) with SMTP id x894Snpn062912 for ; Mon, 9 Sep 2019 04:28:51 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by aserp3030.oracle.com with ESMTP id 2uv2ky9hjj-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK) for ; Mon, 09 Sep 2019 04:28:49 +0000 Received: from abhmp0002.oracle.com (abhmp0002.oracle.com [141.146.116.8]) by aserv0122.oracle.com (8.14.4/8.14.4) with ESMTP id x894SUwI028435 for ; Mon, 9 Sep 2019 04:28:32 GMT Received: from ibhagatpc.us.oracle.com (/10.65.144.100) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Sun, 08 Sep 2019 21:28:29 -0700 From: Indu Bhagat To: gcc-patches@gcc.gnu.org Subject: [PATCH,RFC,V5 4/6] CTF generation for a single compilation unit Date: Sun, 8 Sep 2019 21:28:19 -0700 Message-Id: <1568003301-11457-5-git-send-email-indu.bhagat@oracle.com> In-Reply-To: <1568003301-11457-1-git-send-email-indu.bhagat@oracle.com> References: <1568003301-11457-1-git-send-email-indu.bhagat@oracle.com> For each translation unit, a CTF container (ctf_container_t) is used to keep the CTF debug info. - ctfout.c hosts the compiler facing routines for CTF generation and emission. - ctfcreate.c contains the CTF format specific CTF creation routines. - ctfutils.c contains helper routines for CTF creation. [Changes from V4] Bugfixes and Enhancements: - Use DECL_UID () instead of htab_hash_pointer () for _DECL - Handle boolean and zero-sized bitfields - Do not inform () when skipping types. Arguably this was intended for the GCC developer and not for the end user. - Other bugfixes around de-dupilication at the time of CTF Array or CTF function generation. gcc/ChangeLog * Makefile.in: Add new object files. * ctfcreate.c: New file. * ctfout.c (ctf_dtu_d_union_selector): New helper function for garbage collection of dtd_u union in ctf_dtdef_t. (ctfc_add_cuname): New function to add compilation unit name to CTF container. (ctf_dtdef_hash::hash): New function to generate hashkey for a CTF type record. (hash_dtd_tree_decl): New function. (ctf_dtdef_hash::equal): Likewise. (is_ctf_base_type): Likewise. (get_cvr_quals_for_type): Likewise. (get_type_name_string): Likewise. (get_decl_name_string): Likewise. (ctf_type_exists): Likewise. (init_ctf_string_table): Likewise. (new_ctf_container): Allocate contents of CTF container. (delete_ctf_container): Cleanup contents of CTF container. (init_ctf_sections): Update code comments regarding LTO. (gen_ctf_base_type): New function. (gen_ctf_pointer_type): Likewise. (gen_ctf_array_type): Likewise. (gen_ctf_forward_type): Likewise. (gen_ctf_enum_const_list): Likewise. (gen_ctf_enum_type): Likewise. (gen_ctf_function_type): Likewise. (gen_ctf_cvrquals): Likewise. (gen_ctf_sou_type): Likewise. (gen_ctf_typedef): Likewise. (gen_ctf_variable): Likewise. (gen_ctf_function): Likewise. (gen_ctf_type): Likewise. (gen_ctf_bitfield_type_for_decl): Likewise. (gen_ctf_type_for_decl): Likewise. (ctf_preprocess_var): Likewise. (ctf_dvd_preprocess_cb): Likewise. (ctf_dtd_preprocess_cb): Likewise. (ctf_preprocess): Likewise. (ctf_asm_preamble): Likewise. (ctf_asm_stype): Likewise. (ctf_asm_type): Likewise. (ctf_asm_slice): Likewise. (ctf_asm_array): Likewise. (ctf_asm_varent): Likewise. (ctf_asm_sou_lmember): Likewise. (ctf_asm_sou_member): Likewise. (ctf_asm_enum_const): Likewise. (output_ctf_header): Output the CTF section if the CTF container is not empty. (output_ctf_obj_info): New function. (output_ctf_func_info): Likewise. (output_ctf_objtidx): Likewise. (output_ctf_funcidx): Likewise. (output_ctf_vars): Likewise. (output_ctf_strs): Likewise. (output_asm_ctf_sou_fields): Likewise. (output_asm_ctf_enum_list): Likewise. (output_asm_ctf_vlen_bytes): Likewise. (output_asm_ctf_type): Likewise. (output_ctf_types): Likewise. (ctf_decl): Likewise. (ctf_early_finish): Trigger CTF emission. (ctf_early_global_decl): Invoke CTF generation function. (ctfout_c_finalize): Add cleanup of CTF container. * ctfout.h (typedef struct GTY): New data structures. (struct ctf_dtdef_hash): CTF type structure hasher. * ctfutils.c: New file. include/ChangeLog: * ctf.h: Sync with binutils. Keep ctf_slice_t aligned. Add CTF obj index and func index section. --- gcc/ChangeLog | 70 ++ gcc/Makefile.in | 2 + gcc/ctfcreate.c | 557 ++++++++++++++++ gcc/ctfout.c | 1828 ++++++++++++++++++++++++++++++++++++++++++++++++++++- gcc/ctfout.h | 317 +++++++++- gcc/ctfutils.c | 198 ++++++ include/ChangeLog | 5 + include/ctf.h | 59 +- 8 files changed, 2986 insertions(+), 50 deletions(-) create mode 100644 gcc/ctfcreate.c create mode 100644 gcc/ctfutils.c diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 62d9256..38ff0be 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1257,6 +1257,8 @@ OBJS = \ cfgloopmanip.o \ cfgrtl.o \ ctfout.o \ + ctfutils.o \ + ctfcreate.o \ symtab.o \ cgraph.o \ cgraphbuild.o \ diff --git a/gcc/ctfcreate.c b/gcc/ctfcreate.c new file mode 100644 index 0000000..52c9821 --- /dev/null +++ b/gcc/ctfcreate.c @@ -0,0 +1,557 @@ +/* Functions to create and update CTF from GCC. + Copyright (C) 2019 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +. */ + +/* Create CTF types. The code is mostly adapted from libctf. + + These functions perform the task of adding CTF types to the CTF container. + No de-duplication is done by them; the onus is on the calling function to do + so. The caller must first do a lookup via ctf_dtd_lookup or + ctf_dvd_lookup, as applicable, to ascertain that the CTF type or the CTF + variable respectively does not already exist, and then add it. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "ctfout.h" + +void +ctf_dtd_insert (ctf_container_ref ctfc, ctf_dtdef_ref dtd) +{ + ctf_dtdef_ref entry = dtd; + bool existed = ctfc->ctfc_types->put (entry, dtd); + /* Duplicate CTF type records not expected to be inserted. And dtd_decl + cannot be NULL. */ + gcc_assert (dtd->dtd_decl != NULL && !existed); +} + +/* Lookup CTF type given a tree type or decl node. dtd_key_flags are not + necessary for lookup in most cases, because they are needed only for CTF + types with no corresponding tree type or decl to begin with. */ + +ctf_dtdef_ref +ctf_dtd_lookup (const ctf_container_ref ctfc, const tree type) +{ + return ctf_dtd_lookup_with_flags (ctfc, type, 0); +} + +/* Lookup CTF type given a tree type or decl node and key_flags. */ + +ctf_dtdef_ref +ctf_dtd_lookup_with_flags (const ctf_container_ref ctfc, const tree type, + const unsigned int key_flags) +{ + ctf_dtdef_ref * slot; + + ctf_dtdef_t entry; + entry.dtd_key.dtdk_key_decl = type; + entry.dtd_key.dtdk_key_flags = key_flags; + + slot = ctfc->ctfc_types->get (&entry); + + if (slot) + return (ctf_dtdef_ref) (*slot); + + return NULL; +} + +void +ctf_dvd_insert (ctf_container_ref ctfc, ctf_dvdef_ref dvd) +{ + bool existed = ctfc->ctfc_vars->put (dvd->dvd_decl, dvd); + /* Duplicate variable records not expected to be inserted. And dvd_decl + cannot be NULL. */ + gcc_assert (dvd->dvd_decl != NULL && !existed); +} + +/* Lookup CTF variable given a decl node. */ + +ctf_dvdef_ref +ctf_dvd_lookup (const ctf_container_ref ctfc, const tree decl) +{ + ctf_dvdef_ref * slot; + + slot = ctfc->ctfc_vars->get (decl); + + if (slot) + return (ctf_dvdef_ref) (*slot); + + return NULL; +} + +static ctf_id_t +ctf_add_generic (ctf_container_ref ctfc, uint32_t flag, const char * name, + ctf_dtdef_ref * rp, tree treetype, uint32_t key_flags) +{ + ctf_dtdef_ref dtd; + ctf_id_t type; + + gcc_assert (flag == CTF_ADD_NONROOT || flag == CTF_ADD_ROOT); + + dtd = ggc_cleared_alloc (); + + type = ctfc->ctfc_nextid++; + gcc_assert (type < CTF_MAX_TYPE); /* CTF type ID overflow. */ + + /* Buffer the strings in the CTF string table. */ + dtd->dtd_name = ctf_add_string (ctfc, name, &(dtd->dtd_data.ctti_name)); + dtd->dtd_type = type; + dtd->dtd_key.dtdk_key_decl = treetype; + dtd->dtd_key.dtdk_key_flags = key_flags; + + if ((name != NULL) && strcmp (name, "")) + ctfc->ctfc_strlen += strlen (name) + 1; + + ctf_dtd_insert (ctfc, dtd); + + *rp = dtd; + return type; +} + +static ctf_id_t +ctf_add_encoded (ctf_container_ref ctfc, uint32_t flag, const char * name, + const ctf_encoding_t * ep, uint32_t kind, tree treetype) +{ + ctf_dtdef_ref dtd; + ctf_id_t type; + + type = ctf_add_generic (ctfc, flag, name, &dtd, treetype, 0); + + dtd->dtd_data.ctti_info = CTF_TYPE_INFO (kind, flag, 0); + + uint32_t roundup_nbytes = (ROUND_UP (ep->cte_bits, BITS_PER_UNIT) + / BITS_PER_UNIT); + + /* FIXME, stay close to what libctf does. But by getting next power of two, + aren't we conveying less precise information. E.g. floating point mode + XF has a size of 12 bytes. */ + dtd->dtd_data.ctti_size = roundup_nbytes ? (1 << ceil_log2 (roundup_nbytes)) + : roundup_nbytes; + dtd->dtd_u.dtu_enc = *ep; + + ctfc->ctfc_num_stypes++; + + return type; +} + +static ctf_id_t +ctf_add_reftype (ctf_container_ref ctfc, uint32_t flag, ctf_id_t ref, + uint32_t kind, tree treetype, uint32_t cvrint) +{ + ctf_dtdef_ref dtd; + ctf_id_t type; + uint32_t key_flags = 0; + + /* dtd_key_flags are set only for const, volatile and restrict. */ + if (cvrint && (kind == CTF_K_VOLATILE || kind == CTF_K_CONST + || kind == CTF_K_RESTRICT)) + key_flags = kind; + + gcc_assert (ref <= CTF_MAX_TYPE); + + type = ctf_add_generic (ctfc, flag, NULL, &dtd, treetype, key_flags); + dtd->dtd_data.ctti_info = CTF_TYPE_INFO (kind, flag, 0); + /* Caller of this API must guarantee that a CTF type with id = ref already + exists. This will also be validated for us at link-time. */ + dtd->dtd_data.ctti_type = (uint32_t) ref; + + ctfc->ctfc_num_stypes++; + + return type; +} + +ctf_id_t +ctf_add_forward (ctf_container_ref ctfc, uint32_t flag, const char * name, + uint32_t kind, tree treetype) +{ + ctf_dtdef_ref dtd; + ctf_id_t type = 0; + + gcc_assert (!TYPE_SIZE (treetype)); + /* CTF forward types are inserted with key_flags set to 1 to distinguish them + from the actual struct/union/union with a non-zero size which may be added + later (the latter will be added with key_flags set to 0). */ + uint32_t key_flags = (TYPE_SIZE (treetype) == NULL); + + type = ctf_add_generic (ctfc, flag, name, &dtd, treetype, key_flags); + + dtd->dtd_data.ctti_info = CTF_TYPE_INFO (CTF_K_FORWARD, flag, 0); + dtd->dtd_data.ctti_type = kind; + + ctfc->ctfc_num_stypes++; + + return type; +} + +ctf_id_t +ctf_add_typedef (ctf_container_ref ctfc, uint32_t flag, const char * name, + ctf_id_t ref, tree treetype) +{ + ctf_dtdef_ref dtd; + ctf_id_t type; + + gcc_assert (ref <= CTF_MAX_TYPE); + + type = ctf_add_generic (ctfc, flag, name, &dtd, treetype, 0); + dtd->dtd_data.ctti_info = CTF_TYPE_INFO (CTF_K_TYPEDEF, flag, 0); + /* Caller of this API must guarantee that a CTF type with id = ref already + exists. This will also be validated for us at link-time. */ + dtd->dtd_data.ctti_type = (uint32_t) ref; + + gcc_assert (dtd->dtd_type != dtd->dtd_data.ctti_type); + + ctfc->ctfc_num_stypes++; + + return type; +} + +ctf_id_t +ctf_add_slice (ctf_container_ref ctfc, uint32_t flag, ctf_id_t ref, + const ctf_encoding_t * ep, tree treetype) +{ + ctf_dtdef_ref dtd; + ctf_id_t type; + uint32_t roundup_nbytes; + + gcc_assert ((ep->cte_bits <= 255) && (ep->cte_offset <= 255)); + + gcc_assert (ref <= CTF_MAX_TYPE); + + type = ctf_add_generic (ctfc, flag, NULL, &dtd, treetype, 0); + + dtd->dtd_data.ctti_info = CTF_TYPE_INFO (CTF_K_SLICE, flag, 0); + + roundup_nbytes = (ROUND_UP (ep->cte_bits, BITS_PER_UNIT) / BITS_PER_UNIT); + /* FIXME, stay close to what libctf does. But by getting next power of two, + aren't we conveying less precise information, especially for bitfields. + For example, cte_bits = 33, roundup_nbytes = 5, ctti_size = 8 in the + implementation below. */ + dtd->dtd_data.ctti_size = roundup_nbytes ? (1 << ceil_log2 (roundup_nbytes)) + : 0; + + /* Caller of this API must guarantee that a CTF type with id = ref already + exists. This will also be validated for us at link-time. */ + dtd->dtd_u.dtu_slice.cts_type = (uint32_t) ref; + dtd->dtd_u.dtu_slice.cts_bits = ep->cte_bits; + dtd->dtd_u.dtu_slice.cts_offset = ep->cte_offset; + + ctfc->ctfc_num_stypes++; + + return type; +} + +ctf_id_t +ctf_add_volatile (ctf_container_ref ctfc, uint32_t flag, ctf_id_t ref, + tree type, uint32_t cvrint) +{ + return (ctf_add_reftype (ctfc, flag, ref, CTF_K_VOLATILE, type, cvrint)); +} + +ctf_id_t +ctf_add_const (ctf_container_ref ctfc, uint32_t flag, ctf_id_t ref, + tree type, uint32_t cvrint) +{ + return (ctf_add_reftype (ctfc, flag, ref, CTF_K_CONST, type, cvrint)); +} + +ctf_id_t +ctf_add_restrict (ctf_container_ref ctfc, uint32_t flag, ctf_id_t ref, + tree type, uint32_t cvrint) +{ + return (ctf_add_reftype (ctfc, flag, ref, CTF_K_RESTRICT, type, cvrint)); +} + +ctf_id_t +ctf_add_float (ctf_container_ref ctfc, uint32_t flag, + const char * name, const ctf_encoding_t * ep, tree type) +{ + return (ctf_add_encoded (ctfc, flag, name, ep, CTF_K_FLOAT, type)); +} + +ctf_id_t +ctf_add_integer (ctf_container_ref ctfc, uint32_t flag, + const char * name, const ctf_encoding_t * ep, tree type) +{ + return (ctf_add_encoded (ctfc, flag, name, ep, CTF_K_INTEGER, type)); +} + +ctf_id_t +ctf_add_pointer (ctf_container_ref ctfc, uint32_t flag, ctf_id_t ref, + tree type) +{ + return (ctf_add_reftype (ctfc, flag, ref, CTF_K_POINTER, type, 0)); +} + +ctf_id_t +ctf_add_array (ctf_container_ref ctfc, uint32_t flag, const ctf_arinfo_t * arp, + tree treetype) +{ + ctf_dtdef_ref dtd; + ctf_id_t type; + + gcc_assert (arp); + + /* Caller of this API must make sure CTF type for arp->ctr_contents and + arp->ctr_index are already added. This will also be validated for us at + link-time. */ + + type = ctf_add_generic (ctfc, flag, NULL, &dtd, treetype, 0); + + dtd->dtd_data.ctti_info = CTF_TYPE_INFO (CTF_K_ARRAY, flag, 0); + dtd->dtd_data.ctti_size = 0; + dtd->dtd_u.dtu_arr = *arp; + + ctfc->ctfc_num_stypes++; + + return type; +} + +ctf_id_t +ctf_add_enum (ctf_container_ref ctfc, uint32_t flag, const char * name, + HOST_WIDE_INT size, tree enum_type) +{ + ctf_dtdef_ref dtd; + ctf_id_t type; + + /* In the compiler, no need to handle the case of promoting forwards to + enums. This comment is simply to note a divergence from libctf. */ + + /* The compiler does, however, update any previously existing forward types + to non-root. CTF does not allow existence of two root types with the same + name. */ + ctf_dtdef_ref enum_fwd_type = ctf_dtd_lookup_with_flags (ctfc, enum_type, 1); + if (enum_fwd_type) + { + enum_fwd_type->dtd_data.ctti_info + = CTF_TYPE_INFO (CTF_K_FORWARD, CTF_ADD_NONROOT, 0); + } + + type = ctf_add_generic (ctfc, flag, name, &dtd, enum_type, 0); + + dtd->dtd_data.ctti_info = CTF_TYPE_INFO (CTF_K_ENUM, flag, 0); + + /* Size in bytes should always fit, of course. + TBD WARN - warn instead? */ + gcc_assert (size <= CTF_MAX_SIZE); + + dtd->dtd_data.ctti_size = size; + + ctfc->ctfc_num_stypes++; + + return type; +} + +int +ctf_add_enumerator (ctf_container_ref ctfc, ctf_id_t enid, const char * name, + HOST_WIDE_INT value, tree enum_type) +{ + ctf_dmdef_t * dmd; + uint32_t kind, vlen, root; + + /* Callers of this API must make sure that CTF_K_ENUM with enid has been + addded. This will also be validated for us at link-time. */ + ctf_dtdef_ref dtd = ctf_dtd_lookup (ctfc, enum_type); + gcc_assert (dtd); + gcc_assert (dtd->dtd_type == enid); + gcc_assert (name); + + kind = CTF_V2_INFO_KIND (dtd->dtd_data.ctti_info); + root = CTF_V2_INFO_ISROOT (dtd->dtd_data.ctti_info); + vlen = CTF_V2_INFO_VLEN (dtd->dtd_data.ctti_info); + + gcc_assert (kind == CTF_K_ENUM && vlen < CTF_MAX_VLEN); + + /* Enum value is of type HOST_WIDE_INT in the compiler, dmd_value is int32_t + on the other hand. Check bounds and skip adding this enum value if out of + bounds. */ + if ((value > INT_MAX) || (value < INT_MIN)) + { + /* FIXME - Note this TBD_CTF_REPRESENTATION_LIMIT. */ + return (1); + } + + dmd = ggc_cleared_alloc (); + + /* Buffer the strings in the CTF string table. */ + dmd->dmd_name = ctf_add_string (ctfc, name, &(dmd->dmd_name_offset)); + dmd->dmd_type = CTF_NULL_TYPEID; + dmd->dmd_offset = 0; + + dmd->dmd_value = value; + + dtd->dtd_data.ctti_info = CTF_TYPE_INFO (kind, root, vlen + 1); + ctf_dmd_list_append (&dtd->dtd_u.dtu_members, dmd); + + if ((name != NULL) && strcmp (name, "")) + ctfc->ctfc_strlen += strlen (name) + 1; + + return (0); +} + +int +ctf_add_member_offset (ctf_container_ref ctfc, tree sou, const char * name, + ctf_id_t type, unsigned long bit_offset) +{ + ctf_dtdef_ref dtd = ctf_dtd_lookup (ctfc, sou); + ctf_dmdef_t * dmd; + + uint32_t kind, vlen, root; + + /* The type of the member being added must already exist. */ + gcc_assert (dtd); + + kind = CTF_V2_INFO_KIND (dtd->dtd_data.ctti_info); + root = CTF_V2_INFO_ISROOT (dtd->dtd_data.ctti_info); + vlen = CTF_V2_INFO_VLEN (dtd->dtd_data.ctti_info); + + gcc_assert (kind == CTF_K_STRUCT || kind == CTF_K_UNION); + gcc_assert (vlen < CTF_MAX_VLEN); + +#if 0 + /* Check duplicate members with the same name. May be a useful check if + members of anonymous truct or union are folded into the parent struct (if + exists); See a pending TBD in gen_ctf_sou_type for more info. */ + if (name != NULL) + { + for (dmd = dtd->dtd_u.dtu_members; + dmd != NULL; dmd = (ctf_dmdef_t *) ctf_dmd_list_next (dmd)) + { + if (dmd->dmd_name != NULL) + gcc_assert (strcmp (dmd->dmd_name, name) != 0); + } + } +#endif + + dmd = ggc_cleared_alloc (); + + /* Buffer the strings in the CTF string table. */ + dmd->dmd_name = ctf_add_string (ctfc, name, &(dmd->dmd_name_offset)); + dmd->dmd_type = type; + dmd->dmd_value = -1; + + if (kind == CTF_K_STRUCT && vlen != 0) + dmd->dmd_offset = bit_offset; + else + dmd->dmd_offset = 0; + + dtd->dtd_data.ctti_info = CTF_TYPE_INFO (kind, root, vlen + 1); + ctf_dmd_list_append (&dtd->dtd_u.dtu_members, dmd); + + if ((name != NULL) && strcmp (name, "")) + ctfc->ctfc_strlen += strlen (name) + 1; + + return 0; +} + +int +ctf_add_variable (ctf_container_ref ctfc, const char * name, ctf_id_t ref, + tree decl) +{ + ctf_dvdef_ref dvd; + + gcc_assert (name); + + if (name != NULL) + { + dvd = ggc_cleared_alloc (); + /* Buffer the strings in the CTF string table. */ + dvd->dvd_name = ctf_add_string (ctfc, name, &(dvd->dvd_name_offset)); + dvd->dvd_type = ref; + dvd->dvd_decl = decl; + ctf_dvd_insert (ctfc, dvd); + + if (strcmp (name, "")) + ctfc->ctfc_strlen += strlen (name) + 1; + } + + return 0; +} + +ctf_id_t +ctf_add_function (ctf_container_ref ctfc, uint32_t flag, const char * name, + const ctf_funcinfo_t * ctc, ctf_func_arg_t * argv, + tree func_decl_or_type) +{ + ctf_dtdef_ref dtd; + ctf_id_t type; + uint32_t vlen; + + gcc_assert (ctc); + if (ctc->ctc_argc) + gcc_assert (argv); + + vlen = ctc->ctc_argc; + + /* Caller must make sure CTF types for ctc->ctc_return and function + arguements are already added. */ + + gcc_assert (vlen <= CTF_MAX_VLEN); + + type = ctf_add_generic (ctfc, flag, name, &dtd, func_decl_or_type, 0); + + dtd->dtd_data.ctti_info = CTF_TYPE_INFO (CTF_K_FUNCTION, flag, vlen); + dtd->dtd_data.ctti_type = (uint32_t) ctc->ctc_return; + + dtd->dtd_u.dtu_argv = argv; + + ctfc->ctfc_num_stypes++; + + return type; +} + +ctf_id_t +ctf_add_sou (ctf_container_ref ctfc, uint32_t flag, const char * name, + uint32_t kind, size_t size, tree treetype) +{ + ctf_dtdef_ref dtd; + ctf_id_t type = 0; + + gcc_assert ((kind == CTF_K_STRUCT) || (kind == CTF_K_UNION)); + + /* In the compiler, no need to handle the case of promoting forwards to + structs. This comment is simply to note a divergence from libctf. */ + + /* The compiler does, however, update any previously existing forward types + to non-root. CTF does not allow existence of two root types with the same + name. */ + ctf_dtdef_ref sou_fwd_type = ctf_dtd_lookup_with_flags (ctfc, treetype, 1); + if (sou_fwd_type) + { + sou_fwd_type->dtd_data.ctti_info + = CTF_TYPE_INFO (CTF_K_FORWARD, CTF_ADD_NONROOT, 0); + } + + type = ctf_add_generic (ctfc, flag, name, &dtd, treetype, 0); + + dtd->dtd_data.ctti_info = CTF_TYPE_INFO (kind, flag, 0); + + if (size > CTF_MAX_SIZE) + { + dtd->dtd_data.ctti_size = CTF_LSIZE_SENT; + dtd->dtd_data.ctti_lsizehi = CTF_SIZE_TO_LSIZE_HI (size); + dtd->dtd_data.ctti_lsizelo = CTF_SIZE_TO_LSIZE_LO (size); + ctfc->ctfc_num_types++; + } + else + { + dtd->dtd_data.ctti_size = (uint32_t) size; + ctfc->ctfc_num_stypes++; + } + + return type; +} diff --git a/gcc/ctfout.c b/gcc/ctfout.c index 471cf80..9cee1b7 100644 --- a/gcc/ctfout.c +++ b/gcc/ctfout.c @@ -25,11 +25,13 @@ along with GCC; see the file COPYING3. If not see #include "tree.h" #include "memmodel.h" #include "tm_p.h" +#include "toplev.h" #include "varasm.h" #include "output.h" #include "dwarf2asm.h" #include "debug.h" #include "ctfout.h" +#include "diagnostic-core.h" /* A CTF container object - one per translation unit. */ @@ -43,14 +45,14 @@ static GTY (()) section * ctf_info_section; /* Section names used to hold CTF debugging information. */ +/* CTF debug info section. */ + #ifndef CTF_INFO_SECTION_NAME #define CTF_INFO_SECTION_NAME ".ctf" #endif /* Section flags for the CTF debug info section. */ -/* CTF debug info section. */ - #define CTF_INFO_SECTION_FLAGS (SECTION_DEBUG) /* Maximum size (in bytes) of an artificially generated CTF label. */ @@ -63,8 +65,348 @@ static char ctf_info_section_label[MAX_CTF_LABEL_BYTES]; #define CTF_INFO_SECTION_LABEL "Lctf" #endif +/* Forward declarations for some routines defined in this file. */ + +/* Generate CTF type for the given type. Types already added are skipped. */ + +static ctf_id_t gen_ctf_type (ctf_container_ref, tree); + +/* Generate CTF type for the given decl. Types already added are skipped. */ + +static ctf_id_t gen_ctf_type_for_decl (ctf_container_ref, tree); + +/* CTF preprocess callback arguments. */ + +typedef struct ctf_dtd_preprocess_arg +{ + unsigned long dtd_global_func_idx; + ctf_container_ref dtd_arg_ctfc; +} ctf_dtd_preprocess_arg_t; + +typedef struct ctf_dvd_preprocess_arg +{ + unsigned long dvd_global_obj_idx; + ctf_container_ref dvd_arg_ctfc; +} ctf_dvd_preprocess_arg_t; + +/* CTF cvr qualifier mask. */ + +const int ctf_cvr_qual_mask = (TYPE_QUAL_CONST + | TYPE_QUAL_VOLATILE + | TYPE_QUAL_RESTRICT); + +/* Return which member of the union is used in CTFTYPE. Used for garbage + collection. */ + +enum ctf_dtu_d_union_enum +ctf_dtu_d_union_selector (ctf_dtdef_ref ctftype) +{ + unsigned int kind = CTF_V2_INFO_KIND (ctftype->dtd_data.ctti_info); + switch (kind) + { + case CTF_K_INTEGER: + case CTF_K_FLOAT: + return CTF_DTU_D_ENCODING; + case CTF_K_STRUCT: + case CTF_K_UNION: + case CTF_K_ENUM: + return CTF_DTU_D_MEMBERS; + case CTF_K_ARRAY: + return CTF_DTU_D_ARRAY; + case CTF_K_FUNCTION: + return CTF_DTU_D_ARGUMENTS; + case CTF_K_SLICE: + return CTF_DTU_D_SLICE; + default: + /* The largest member as default. */ + return CTF_DTU_D_ARRAY; + } +} + +/* Add the compilation unit (CU) name string to the the CTF string table. The + CU name has a prepended pwd string if it is a relative path. Also set the + CU name offset in the CTF container. */ + +static void +ctfc_add_cuname (ctf_container_ref ctfc, const char * filename) +{ + char * cuname = NULL; + + /* (filename at this point of compilation cannot be null). */ + + if (!IS_DIR_SEPARATOR (filename[0])) + { + /* Filename is a relative path. */ + const char * cu_pwd = get_src_pwd (); + const int cu_pwd_len = strlen (cu_pwd); + + /* Add a DIR_SEPARATOR char before the filename. */ + const int len = cu_pwd_len + 2 + strlen (filename); + + cuname = (char *) ggc_alloc_atomic (len); + memset (cuname, 0, len); + + strcpy (cuname, cu_pwd); + cuname[cu_pwd_len] = DIR_SEPARATOR; + cuname[cu_pwd_len+1] = 0; + strcat (cuname, filename); + } + else + /* Filename is an absolute path. */ + cuname = CONST_CAST (char *, ggc_strdup (filename)); + + ctf_add_string (ctfc, cuname, &(ctfc->ctfc_cuname_offset)); + /* Add 1 as CTF strings in the CTF string table are null-terminated + strings. */ + ctfc->ctfc_strlen += strlen (cuname) + 1; + + /* Mark cuname for garbage collection. */ + cuname = NULL; +} + +/* Returns a hash code for CTF type records. */ + +hashval_t +ctf_dtdef_hash::hash (ctf_dtdef_ref e1) +{ + ctf_dtdef_ref e = e1; + tree e_decl = e->dtd_decl; + uint32_t key_flags = e->dtd_key_flags; + + hashval_t key = hash_dtd_tree_decl (e_decl, key_flags); + + return key; +} + +hashval_t +hash_dtd_tree_decl (tree e_decl, uint32_t key_flags) +{ + hashval_t key; + tree type = NULL; + + if ((TREE_CODE (e_decl) == FIELD_DECL) + || (TREE_CODE (e_decl) == TYPE_DECL)) + type = TREE_TYPE (e_decl); + else + type = e_decl; /* TREE_TYPE was used as dtd_key otherwise. */ + + if (TREE_CODE (e_decl) == TYPE_DECL + || TREE_CODE (e_decl) == FUNCTION_DECL + /* No CTF type de-duplication for slices. See note in + gen_ctf_bitfield_type_for_decl. */ + || ((TREE_CODE (e_decl) == FIELD_DECL) && DECL_BIT_FIELD_TYPE (e_decl))) + { + key = (hashval_t) DECL_UID (e_decl); + } + else + { + gcc_assert (TREE_CODE_CLASS (TREE_CODE (type)) == tcc_type); + key = (hashval_t) TYPE_UID (type); + } + + if (key_flags) + key = iterative_hash (&key_flags, sizeof (key_flags), key); + + return key; +} + +/* Returns nonzero if entry1 and entry2 are the same CTF types. */ + +bool +ctf_dtdef_hash::equal (ctf_dtdef_ref entry1, ctf_dtdef_ref entry2) +{ + bool eq = 0; + tree e1_type, e2_type; + int e1_cvr_quals = 0, e2_cvr_quals = 0; + + ctf_dtdef_ref e1 = entry1; + ctf_dtdef_ref e2 = entry2; + + tree e1_decl = e1->dtd_decl; + tree e2_decl = e2->dtd_decl; + + gcc_assert (e1_decl); + gcc_assert (e2_decl); + /* This pre-check is useful because dtd_decl can be either type or decl tree + references. */ + eq = (TREE_CODE (e1_decl) == TREE_CODE (e2_decl)); + if (eq) + { + if ((TREE_CODE (e1_decl) == FIELD_DECL) + || (TREE_CODE (e1_decl) == TYPE_DECL)) + { + e1_type = TREE_TYPE (e1_decl); + e2_type = TREE_TYPE (e2_decl); + } + else + { + /* TREE_TYPE was used as dtd_key otherwise. */ + e1_type = e1_decl; + e2_type = e2_decl; + } + + if (TREE_CODE (e1_decl) == TYPE_DECL + || TREE_CODE (e1_decl) == FUNCTION_DECL + /* No CTF type de-duplication for slices. See note in + gen_ctf_bitfield_type_for_decl. */ + || ((TREE_CODE (e1_decl) == FIELD_DECL) + && DECL_BIT_FIELD_TYPE (e1_decl))) + + { + eq = (DECL_UID (e1_decl) == DECL_UID (e2_decl)); + } + else + { + gcc_assert (TREE_CODE_CLASS (TREE_CODE (e1_type)) == tcc_type); + gcc_assert (TREE_CODE_CLASS (TREE_CODE (e2_type)) == tcc_type); + + eq = (TYPE_UID (e1_type) == TYPE_UID (e2_type)); + + /* Always compare cvr_quals when available. */ + e1_cvr_quals = (TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC (e1_type) + & ctf_cvr_qual_mask); + e2_cvr_quals = (TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC (e2_type) + & ctf_cvr_qual_mask); + + if (eq && e1_cvr_quals) + { + e2_cvr_quals = (TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC (e2_type) + & ctf_cvr_qual_mask); + eq = (e1_cvr_quals == e2_cvr_quals); + } + } + + if (eq) + { + /* dtd_key_flags are set only for CTF type records which have no + direct corresponding tree type or decl. They will be 0 + otherwise. */ + eq = (e1->dtd_key_flags == e2->dtd_key_flags); + } + } + + return eq; +} + +static inline int +is_ctf_base_type (tree type) +{ + switch (TREE_CODE (type)) + { + case INTEGER_TYPE: + case REAL_TYPE: + case FIXED_POINT_TYPE: + case COMPLEX_TYPE: + case BOOLEAN_TYPE: + case VOID_TYPE: + return 1; + + case ARRAY_TYPE: + case RECORD_TYPE: + case UNION_TYPE: + case QUAL_UNION_TYPE: + case ENUMERAL_TYPE: + case FUNCTION_TYPE: + case METHOD_TYPE: + case POINTER_TYPE: + case REFERENCE_TYPE: + case NULLPTR_TYPE: + case OFFSET_TYPE: + case LANG_TYPE: + case VECTOR_TYPE: + return 0; + + default: + gcc_unreachable (); + } + + return 0; +} + +static inline int +get_cvr_quals_for_type (tree type) +{ + int cvr_quals = 0; + + if (TREE_CODE_CLASS (TREE_CODE (type)) == tcc_type) + cvr_quals = TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC (type); + + return cvr_quals; +} + +static const char * +get_type_name_string (tree type) +{ + gcc_assert (TREE_CODE_CLASS (TREE_CODE (type)) == tcc_type); + + tree type_name = TYPE_IDENTIFIER (type); + const char * name_string = type_name ? IDENTIFIER_POINTER (type_name) : NULL; + + return name_string; +} + +static const char * +get_decl_name_string (tree decl) +{ + gcc_assert (TREE_CODE_CLASS (TREE_CODE (decl)) == tcc_declaration); + + tree decl_name = DECL_NAME (decl); + const char * name_string = decl_name ? IDENTIFIER_POINTER (decl_name) : NULL; + + return name_string; +} + +/* Check if CTF for TYPE has already been generated. Mainstay for + de-duplication. If CTF type already exists, returns TRUE and updates + the TYPE_ID for the caller. */ + +static bool +ctf_type_exists (ctf_container_ref ctfc, tree type, + ctf_id_t * type_id) +{ + bool exists = false; + uint32_t key_flags = 0; + + /* In the same compilation unit, use key_flags to differentiate a forward + type from the struct/union/enum definition which may follow later. Both + must be CTF encoded for completeness. */ + if (RECORD_OR_UNION_TYPE_P (type) || TREE_CODE (type) == ENUMERAL_TYPE) + key_flags = (TYPE_SIZE (type) == NULL); + + ctf_dtdef_ref ctf_type_seen + = ctf_dtd_lookup_with_flags (ctfc, type, key_flags); + + if (ctf_type_seen) + { + exists = true; + /* CTF type for this type exists. */ + *type_id = ctf_type_seen->dtd_type; + } + + return exists; +} + /* CTF container setup and teardown routines. */ +/* Initialize the CTF string table. + The first entry in the CTF string table (empty string) is added. */ + +static void +init_ctf_string_table (ctf_container_ref ctfc) +{ + ctfc->ctfc_strtable.ctstab_head = NULL; + ctfc->ctfc_strtable.ctstab_tail = NULL; + ctfc->ctfc_strtable.ctstab_num = 0; + ctfc->ctfc_strtable.ctstab_len = 0; + + /* The first entry in the CTF string table is an empty string. E.g., CTF + type records with no name (like CTF_K_CONST, CTF_K_VOLATILE etc) point to + this string. */ + uint32_t estr_offset = 0; + ctfc->ctfc_strtable.ctstab_estr = ctf_add_string (ctfc, "", &estr_offset); + ctfc->ctfc_strlen++; +} + /* Allocate a new CTF container with the desired flags. */ static inline ctf_container_ref @@ -75,6 +417,15 @@ new_ctf_container (unsigned char ctp_flags) tu_ctfc->ctfc_magic = CTF_MAGIC; tu_ctfc->ctfc_version = CTF_VERSION; tu_ctfc->ctfc_flags = ctp_flags; + tu_ctfc->ctfc_nextid = CTF_INIT_TYPEID; + + tu_ctfc->ctfc_types + = hash_map::create_ggc (100); + + tu_ctfc->ctfc_vars + = hash_map::create_ggc (100); + + init_ctf_string_table (tu_ctfc); return tu_ctfc; } @@ -97,7 +448,28 @@ delete_ctf_container (ctf_container_ref ctfc) including the hash_map members etc. ? */ if (ctfc) { - ctfc = NULL; + if (ctfc->ctfc_vars_list) + { + ggc_free (ctfc->ctfc_vars_list); + ctfc->ctfc_vars_list = NULL; + } + if (ctfc->ctfc_types_list) + { + ggc_free (ctfc->ctfc_types_list); + ctfc->ctfc_types_list = NULL; + } + if (ctfc->ctfc_gfuncs_list) + { + ggc_free (ctfc->ctfc_gfuncs_list); + ctfc->ctfc_gfuncs_list = NULL; + } + if (ctfc->ctfc_gobjts_list) + { + ggc_free (ctfc->ctfc_gobjts_list); + ctfc->ctfc_gobjts_list = NULL; + } + + ctfc= NULL; } } @@ -106,59 +478,1452 @@ delete_ctf_container (ctf_container_ref ctfc) void init_ctf_sections (void) { - ctf_info_section = get_section (CTF_INFO_SECTION_NAME, - CTF_INFO_SECTION_FLAGS, + /* Note : Even in case of LTO, the compiler continues to generate a single + CTF section for each compilation unit "early". Unlike other debug + sections, CTF sections are non-LTO sections, and do not take the + .gnu.debuglto_ prefix. The linker will de-duplicate the types in the CTF + sections, in case of LTO or otherwise. */ + ctf_info_section = get_section (CTF_INFO_SECTION_NAME, CTF_INFO_SECTION_FLAGS, NULL); + ASM_GENERATE_INTERNAL_LABEL (ctf_info_section_label, CTF_INFO_SECTION_LABEL, ctf_label_num++); } -/* Asm'out the CTF preamble. */ +/* Leaf routines for CTF type generation. + Called via the gen_ctf_type (), these APIs update the CTF container with new + CTF records. CTF type de-duplication must be done by the caller API + (See "Parent routines for CTF generation below). */ -static void -ctf_asm_preamble (ctf_container_ref ctfc) +/* Generate CTF for base type (integer, boolean, real, fixed point and complex). + Important: the caller of this API must make sure that duplicate types are + not added. */ + +static ctf_id_t +gen_ctf_base_type (ctf_container_ref ctfc, tree type) { - dw2_asm_output_data (2, ctfc->ctfc_magic, - "CTF preamble magic number"); - dw2_asm_output_data (1, ctfc->ctfc_version, "CTF preamble version"); - dw2_asm_output_data (1, ctfc->ctfc_flags, "CTF preamble flags"); + ctf_id_t type_id = CTF_NULL_TYPEID; + + ctf_encoding_t ctf_encoding = {0, 0, 0}; + HOST_WIDE_INT size = int_size_in_bytes (type); + + uint32_t encoding = 0; + + const char * name_string = get_type_name_string (type); + /* Base TYPE node must have had a TYPE_IDENTIFIER node, else retrieval of + name string of the base type will need to be adjusted. */ + /* This assert here fails for "complex char a". CTF skips these types. But + need to debug why the TYPE_NAME is null. FIXME - moved the asserts into + each respective block below meanwhile. */ + // gcc_assert (name_string); + + /* Add the type of variable. */ + switch (TREE_CODE (type)) + { + case INTEGER_TYPE: + { + /* Note - CTF_INT_VARARGS is unused in CTF. */ + + /* Update size and encoding. */ + if (TYPE_STRING_FLAG (type)) + { + if (TYPE_UNSIGNED (type)) + encoding = CTF_INT_CHAR; + else + encoding = CTF_INT_CHAR | CTF_INT_SIGNED; + } + else if (!TYPE_UNSIGNED (type)) + encoding = CTF_INT_SIGNED; + + ctf_encoding.cte_format = encoding; + ctf_encoding.cte_bits = size * BITS_PER_UNIT; + + gcc_assert (name_string); + type_id = ctf_add_integer (ctfc, CTF_ADD_ROOT, name_string, + &ctf_encoding, type); + + break; + } + + case BOOLEAN_TYPE: + encoding = CTF_INT_BOOL; + + ctf_encoding.cte_format = encoding; + ctf_encoding.cte_bits = size * BITS_PER_UNIT; + + gcc_assert (name_string); + type_id = ctf_add_integer (ctfc, CTF_ADD_ROOT, name_string, + &ctf_encoding, type); + break; + + case REAL_TYPE: + if (FLOAT_MODE_P (TYPE_MODE (type))) + { + if (size == int_size_in_bytes (float_type_node)) + encoding = CTF_FP_SINGLE; + else if (size == int_size_in_bytes (double_type_node)) + encoding = CTF_FP_DOUBLE; + else if ((size == int_size_in_bytes (long_double_type_node)) + || (size == int_size_in_bytes (float128_type_node))) + encoding = CTF_FP_LDOUBLE; + /* Encoding must be appropriately initialized by now. */ + gcc_assert (encoding && encoding <= CTF_FP_MAX); + + ctf_encoding.cte_format = encoding; + ctf_encoding.cte_bits = size * BITS_PER_UNIT; + + gcc_assert (name_string); + type_id = ctf_add_float (ctfc, CTF_ADD_ROOT, name_string, + &ctf_encoding, type); + } + + /* CTF does not have representation for non IEEE float encoding. Skip + this type. FIXME - Note this TBD_CTF_REPRESENTATION_LIMIT. */ + break; + + case FIXED_POINT_TYPE: + /* CTF does not have representation for fixed point type. Skip this type. + FIXME - Note this TBD_CTF_REPRESENTATION_LIMIT. */ + break; + + case COMPLEX_TYPE: + encoding = 0; + if (TREE_CODE (TREE_TYPE (type)) == REAL_TYPE) + { + tree component_type = TREE_TYPE (type); + size = int_size_in_bytes (component_type); + + if (size == int_size_in_bytes (float_type_node)) + encoding = CTF_FP_CPLX; + else if (size == int_size_in_bytes (double_type_node)) + encoding = CTF_FP_DCPLX; + else if ((size == int_size_in_bytes (long_double_type_node)) + || (size == int_size_in_bytes (float128_type_node))) + encoding = CTF_FP_LDCPLX; + + /* Encoding must be appropriately initialized by now. */ + gcc_assert (encoding && encoding != CTF_FP_MAX); + + ctf_encoding.cte_format = encoding; + ctf_encoding.cte_bits = size * BITS_PER_UNIT; + + gcc_assert (name_string); + type_id = ctf_add_float (ctfc, CTF_ADD_ROOT, name_string, + &ctf_encoding, type); + } + /* CTF does not have representation for complex integer type. Skip this + type. FIXME - Note this TBD_CTF_REPRESENTATION_LIMIT. */ + break; + + case VOID_TYPE: + encoding = CTF_INT_SIGNED; + ctf_encoding.cte_format = encoding; + ctf_encoding.cte_bits = 0; + + gcc_assert (name_string); + type_id = ctf_add_integer (ctfc, CTF_ADD_ROOT, name_string, + &ctf_encoding, type); + + break; + + default: + /* No other TREE_CODEs are expected as CTF base types. */ + gcc_unreachable () ; + } + + return type_id; +} + +static ctf_id_t +gen_ctf_pointer_type (ctf_container_ref ctfc, tree ptr_type) +{ + ctf_id_t type_id = CTF_NULL_TYPEID; + ctf_id_t pointer_to_type_id = CTF_NULL_TYPEID; + + tree pointertotype = TREE_TYPE (ptr_type); + + type_id = gen_ctf_type (ctfc, pointertotype); + + /* Type de-duplication. + Consult the ctfc_types hash again before adding the CTF pointer type + because there can be cases where a pointer type may have been added by + the gen_ctf_type call above. For example, a struct have a member of type + pointer to the struct, e.g., + struct link { struct link * next; } * slink; */ + if (ctf_type_exists (ctfc, ptr_type, &pointer_to_type_id)) + return pointer_to_type_id; + + pointer_to_type_id = ctf_add_pointer (ctfc, CTF_ADD_ROOT, type_id, + ptr_type); + + return pointer_to_type_id; +} + +static ctf_id_t +gen_ctf_array_type (ctf_container_ref ctfc, tree array_type) +{ + ctf_id_t type_id = CTF_NULL_TYPEID; + tree lower, upper; + ctf_arinfo_t arinfo; + HOST_WIDE_INT min_index = 0, max_index = 0; + uint32_t num_elements = 0; + ctf_id_t ctf_contents_type_id = CTF_NULL_TYPEID; + ctf_id_t ctf_index_type_id = CTF_NULL_TYPEID; + + tree type_of_array_element = TREE_TYPE (array_type); + tree type_of_index = TYPE_DOMAIN (array_type); + + /* type_of_index may be NULL in some cases, e.g., when we parse + extern const char _var_example[]; + In this case of unsized uninitialized array declaration, CTF encodes an + explicit zero for the number of elements. This is quite distinct from + DWARF which encodes no bound information in such a case. + TBD_CTF_FORMAT_OPEN_ISSUES (1) - see testcase ctf-array-2.c. */ + if (type_of_index) + { + lower = TYPE_MIN_VALUE (type_of_index); + upper = TYPE_MAX_VALUE (type_of_index); + min_index = tree_to_shwi (lower); + /* TYPE_MAX_VALUE of index may be null for variable-length arrays. */ + max_index = upper ? tree_to_shwi (upper) : 0; + if (max_index > 0) gcc_assert (max_index >= min_index); + /* If max_index == min_index, both the values must be zero; num_elements + set to zero in that case. */ + num_elements = (max_index > 0 && max_index > min_index) + ? max_index - min_index + 1 : 0; + gcc_assert (num_elements <= CTF_MAX_SIZE); + } + + arinfo.ctr_nelems = num_elements; + + /* Overwrite the type_of_index with integer_type_node. + TYPE_DOMAIN of ARRAY_TYPE have code INTEGER_TYPE, but have no + IDENTIFIER_NODES. This causes issues in retrieving the name string of + the index type (See gen_ctf_base_type) becuase the TYPE_IDENTIFIER is NULL + in those cases. + Use integer_type_node instead. This also helps gen_ctf_base_type to not + generate crooked (and duplicate) int records with wierd "integer" size for + arrays. */ + type_of_index = integer_type_node; + + ctf_index_type_id = gen_ctf_type (ctfc, type_of_index); + arinfo.ctr_index = ctf_index_type_id; + + ctf_contents_type_id = gen_ctf_type (ctfc, type_of_array_element); + arinfo.ctr_contents = ctf_contents_type_id; + + /* Type de-duplication. + Consult the ctfc_types hash again before adding the CTF array type because + there can be cases where an array_type type may have been added by the + gen_ctf_type call above. */ + if (!ctf_type_exists (ctfc, array_type, &type_id)) + type_id = ctf_add_array (ctfc, CTF_ADD_ROOT, &arinfo, array_type); + + return type_id; } -/* Output the CTF header. */ +static ctf_id_t +gen_ctf_forward_type (ctf_container_ref ctfc, tree fwd_type, uint32_t kind) +{ + ctf_id_t fwd_type_id = 0; + + const char * fwd_name = get_type_name_string (fwd_type); + /* Type de-duplication is already done by now. See gen_ctf_type (). + Simple add the forward type. */ + fwd_type_id = ctf_add_forward (ctfc, CTF_ADD_ROOT, fwd_name, kind, fwd_type); + + return fwd_type_id; +} static void -output_ctf_header (ctf_container_ref ctfc) +gen_ctf_enum_const_list (ctf_container_ref ctfc, const tree enum_type, + const ctf_id_t enum_type_id) { - switch_to_section (ctf_info_section); - ASM_OUTPUT_LABEL (asm_out_file, ctf_info_section_label); + tree link; + tree enum_value; + HOST_WIDE_INT value; + /* Append the enum values to the CTF_K_ENUM record. */ + for (link = TYPE_VALUES (enum_type); link != NULL; link = TREE_CHAIN (link)) + { + enum_value = TREE_VALUE (link); + /* For now, handle enumeration constants not wider than + HOST_WIDE_INT. TBD handle this. */ + gcc_assert (int_size_in_bytes (TREE_TYPE (enum_value))*HOST_BITS_PER_CHAR + <= HOST_BITS_PER_WIDE_INT || tree_fits_shwi_p (enum_value)); - ctf_asm_preamble (ctfc); + value = TREE_INT_CST_LOW (enum_value); + const char * enum_valname = IDENTIFIER_POINTER (TREE_PURPOSE (link)); + gcc_assert (enum_valname); + + ctf_add_enumerator (ctfc, enum_type_id, enum_valname, value, enum_type); + + /* ctf_add_enumerator returns true if addition of the enumeration + constant is skipped if not representable in CTF (int32_t). + FIXME - Note this TBD_CTF_REPRESENTATION_LIMIT. */ + } } -/* CTF routines interfacing to the compiler. */ +static ctf_id_t +gen_ctf_enum_type (ctf_container_ref ctfc, tree enum_type) +{ + ctf_id_t enum_type_id = CTF_NULL_TYPEID; + HOST_WIDE_INT size; -void -ctf_debug_init (void) + gcc_assert (TREE_CODE (enum_type) == ENUMERAL_TYPE); + + if (!TYPE_SIZE (enum_type)) + { + /* Add CTF forward type of enum kind. */ + uint32_t kind = CTF_K_ENUM; + enum_type_id = gen_ctf_forward_type (ctfc, enum_type, kind); + return enum_type_id; + } + + const char * enum_name = get_type_name_string (enum_type); + size = int_size_in_bytes (enum_type); + + /* Add CTF enum type. */ + enum_type_id = ctf_add_enum (ctfc, CTF_ADD_ROOT, enum_name, size, enum_type); + /* Add CTF records for enum const values. */ + gen_ctf_enum_const_list (ctfc, enum_type, enum_type_id); + + return enum_type_id; +} + +static ctf_id_t +gen_ctf_function_type (ctf_container_ref ctfc, tree func_decl_or_type, + const char * func_name) { - init_ctf_containers (); + ctf_id_t type_id = CTF_NULL_TYPEID, return_type_id = CTF_NULL_TYPEID; + tree func_type; + tree link; + tree first_param_type; + tree formal_type = NULL; + tree return_type = NULL; + tree param_type; + uint32_t num_args = 0; + ctf_func_arg_t * argv_ids; + ctf_funcinfo_t func_info; + + if (TREE_CODE (func_decl_or_type) == FUNCTION_TYPE) + func_type = func_decl_or_type; + else + func_type = TREE_TYPE (func_decl_or_type); + + return_type = TREE_TYPE (func_type); + first_param_type = TYPE_ARG_TYPES (func_type); + + /* Add CTF record for function return type. */ + return_type_id = gen_ctf_type (ctfc, return_type); + func_info.ctc_return = return_type_id; + + /* Make our first pass over the list of formal parameter types and count + them. */ + for (link = first_param_type; link;) + { + formal_type = TREE_VALUE (link); + if (formal_type == void_type_node) + break; + + num_args++; + + link = TREE_CHAIN (link); + } + + /* Check if this function type has an ellipsis. */ + if (formal_type != void_type_node) + { + func_info.ctc_flags |= CTF_FUNC_VARARG; + /* Increment the number of args. This is the number of args we write + after the CTF_K_FUNCTION CTF record. */ + num_args++; + } + + /* The number of typed arguments should include the ellipsis. */ + func_info.ctc_argc = num_args; + + /* Create an array of ctf_id_t to hold CTF types for args (including the + ellipsis). */ + argv_ids = ggc_vec_alloc(num_args); + + /* Make a pass over the list of formal parameter types and generate CTF for + each. */ + unsigned int i = 0; + for (link = TYPE_ARG_TYPES (func_type); + link && TREE_VALUE (link); + link = TREE_CHAIN (link)) + { + param_type = TREE_VALUE (link); + + if (param_type == void_type_node) + break; + + argv_ids[i++].farg_type = gen_ctf_type (ctfc, param_type); + } + + if (formal_type != void_type_node) + { + /* Add trailing zero to indicate varargs. */ + argv_ids[i].farg_type = 0; + gcc_assert (i == num_args - 1); + } + + /* Type de-duplication. + Consult the ctfc_types hash again before adding the CTF function type + because there can be cases where a function type may have been added by + the gen_ctf_type call above. For example, + struct callback_head { + struct callback_head *next; + void (*func) (struct callback_head *head); + } __attribute__ (( aligned (sizeof (void *)))); + #define rcu_head callback_head + + typedef void (*rcu_callback_t) (struct rcu_head *head); */ + if (ctf_type_exists (ctfc, func_decl_or_type, &type_id)) + argv_ids = NULL; + else + type_id = ctf_add_function (ctfc, CTF_ADD_ROOT, func_name, + (const ctf_funcinfo_t *)&func_info, argv_ids, + func_decl_or_type); + + return type_id; } -void -ctf_early_finish (const char * ARG_UNUSED (filename)) +/* Add CTF qualifier record. + + If there are multiple qualifiers, the recommended ordering for CTF qualifier + records is const, volatile, restrict (from top-most to bottom-most). */ + +static ctf_id_t +gen_ctf_cvrquals (ctf_container_ref ctfc, tree type, ctf_id_t type_id) { - if (ctf_debug_info_level == CTFINFO_LEVEL_NONE) - return; + tree qualified_type; + int flags; + uint32_t cvrint = 0; + int quals_index = 0; - init_ctf_sections (); + ctf_id_t qual_type_id = type_id; + int cvr_quals = get_cvr_quals_for_type (type); - output_ctf_header (tu_ctfc); + int quals_order[3] = { TYPE_QUAL_RESTRICT, + TYPE_QUAL_VOLATILE, + TYPE_QUAL_CONST }; + ctf_id_t (*func_ptrs[3]) (ctf_container_ref, uint32_t, ctf_id_t, tree, + uint32_t) = { ctf_add_restrict, + ctf_add_volatile, + ctf_add_const }; + unsigned int key_flags[3] = { CTF_K_RESTRICT, CTF_K_VOLATILE, CTF_K_CONST }; + ctf_id_t (*ctf_add_qual_func) (ctf_container_ref, uint32_t, ctf_id_t, tree, + uint32_t); + + qualified_type = get_qualified_type (type, cvr_quals); + + /* Type de-duplication for cvr records. + Do not add CTF types for the same type with the matching cvr qual + if already present. */ + if (qualified_type) + { + if (ctf_type_exists (ctfc, qualified_type, &qual_type_id)) + return qual_type_id; + } + else + /* If the qualified_type is NULL, use TREE_TYPE of the decl to add + the CTF record. CTF for unqualified type must have been added by + now. */ + gcc_assert (ctf_type_exists (ctfc, type, &qual_type_id)); + + /* CTF represents distinct type records for each qualifier (CTF_K_RESTRICT, + CTF_K_VOLATILE, CTF_K_CONST). The records can be shared between types. + Here we try to de-duplicate these records as well. */ + while (cvr_quals) + { + flags = cvr_quals & quals_order[quals_index]; + ctf_add_qual_func = func_ptrs[quals_index]; + if (flags) + { + cvrint = (cvr_quals != 0); + /* Reset the corresponding cvr_qual flag so that it is not processed + again. */ + cvr_quals &= ~quals_order[quals_index]; + + /* The dtd_decl of the all CTF type records should be non-null for + de-duplication to work. CTF records for CVR quals of a type will + have the same dtd_decl in this case. So, to prevent collisions, we + use dtd_decl and dtd_key_flags for creating the hashkey. */ + ctf_dtdef_ref qual_type_exists + = ctf_dtd_lookup_with_flags (ctfc, type, key_flags[quals_index]); + if (qual_type_exists) + qual_type_id = qual_type_exists->dtd_type; + else + qual_type_id = ctf_add_qual_func (ctfc, CTF_ADD_ROOT, qual_type_id, + type, cvrint); + } + quals_index++; + } + + /* At least one CTF record must have been added or found to be duplicate + by now. */ + gcc_assert (qual_type_id != type_id); + + return qual_type_id; } -void -ctf_early_global_decl (tree ARG_UNUSED (decl)) +static ctf_id_t +gen_ctf_sou_type (ctf_container_ref ctfc, tree sou_type) { - /* Generate CTF type information if appropriate debug level is set - (ctf_debug_info_level == CTFINFO_LEVEL_NORMAL). */ + HOST_WIDE_INT sou_size; + + ctf_id_t sou_type_id = CTF_NULL_TYPEID; + ctf_id_t field_type_id = CTF_NULL_TYPEID; + + tree field; + HOST_WIDE_INT bit_offset = 0; + + gcc_assert (RECORD_OR_UNION_TYPE_P (sou_type)); + + /* Handle anonymous record or union. */ +#if 0 + if (TYPE_NAME (sou_type) == NULL) + { + /* TBD - confirm this behaviour. + The compiler will not flatten an anonymous struct or union into its + parent if one exists. Members of anonymous struct or union continue + to be wrappped by the respective anonymous record. */ + } +#endif + uint32_t kind = (TREE_CODE (sou_type) == RECORD_TYPE) + ? CTF_K_STRUCT : CTF_K_UNION; + + if (!TYPE_SIZE (sou_type)) + { + /* Add CTF forward type of struct or union kind. */ + sou_type_id = gen_ctf_forward_type (ctfc, sou_type, kind); + return sou_type_id; + } + + const char * sou_name = get_type_name_string (sou_type); + sou_size = int_size_in_bytes (sou_type); + + /* Add CTF struct/union type. */ + if ((TREE_CODE (sou_type) == RECORD_TYPE) + || (TREE_CODE (sou_type) == UNION_TYPE)) + sou_type_id = ctf_add_sou (ctfc, CTF_ADD_ROOT, sou_name, kind, sou_size, + sou_type); + /* QUAL_UNION_TYPE not expected in C. */ + else + gcc_unreachable (); + + /* Add members of the struct. */ + for (field = TYPE_FIELDS (sou_type); field != NULL_TREE; + field = TREE_CHAIN (field)) + { + /* Enum members have DECL_NAME (field) as NULL. */ + const char * field_name = get_decl_name_string (field); + + /* variable bit offsets are not handled at the moment. */ + gcc_assert (TREE_CODE (DECL_FIELD_BIT_OFFSET (field)) == INTEGER_CST); + + bit_offset = int_bit_position (field); + /* Add the CTF type record for the field, followed by the field + itself. */ + field_type_id = gen_ctf_type_for_decl (ctfc, field); + ctf_add_member_offset (ctfc, sou_type, field_name, field_type_id, + bit_offset); + } + + return sou_type_id; +} + +/* Parent routines for CTF generation. + These routines are entry points for CTF generation. Given a type or decl, + these routines perform de-duplication before invoking the Leaf CTF + generation routines for adding types. */ + +/* Generate CTF typedef records for a given declaration. Performs + de-duplication before adding typedef. */ + +static ctf_id_t +gen_ctf_typedef (ctf_container_ref ctfc, tree decl) +{ + ctf_id_t type_id = CTF_NULL_TYPEID, typedef_type_id = CTF_NULL_TYPEID; + + tree type = TREE_TYPE (decl); + const char * decl_name_string = get_type_name_string (type); + + /* CTF type de-duplication in the compiler. + Do not add duplicate typedef. */ + if (ctf_type_exists (ctfc, decl, &type_id)) + return type_id; + + /* Generate the type if not already done. */ + type_id = gen_ctf_type_for_decl (ctfc, decl); + + /* Add typedef. dtd_decl points to the typedef tree node. */ + typedef_type_id = ctf_add_typedef (ctfc, CTF_ADD_ROOT, decl_name_string, + type_id, decl); + type_id = typedef_type_id; + + return type_id; +} + +/* Generate CTF variable records for a given declaration. Performs + de-duplication before adding variable. */ + +static ctf_id_t +gen_ctf_variable (ctf_container_ref ctfc, tree decl) +{ + ctf_id_t type_id = CTF_NULL_TYPEID, var_type_id = CTF_NULL_TYPEID; + + const char* name = get_decl_name_string (decl); + + ctf_dvdef_ref var_type_seen = ctf_dvd_lookup (tu_ctfc, decl); + /* Avoid duplicates. A VAR_DECL is duplicate if it is the same decl node. + See hash_dvd_tree_decl. */ + if (!var_type_seen) + { + type_id = gen_ctf_type_for_decl (ctfc, decl); + /* Now add the variable. */ + var_type_id = ctf_add_variable (tu_ctfc, name, type_id, decl); + + /* Update global objects count. */ + if (TREE_PUBLIC (decl)) + ctfc->ctfc_num_global_objts++; + } + else + var_type_id = var_type_seen->dvd_type; + + return var_type_id; +} + +/* Generate CTF function records for a given declaration. */ + +static ctf_id_t +gen_ctf_function (ctf_container_ref ctfc, tree func_decl) +{ + gcc_assert (TREE_CODE (func_decl) == FUNCTION_DECL); + + ctf_id_t type_id = CTF_NULL_TYPEID; + + const char * func_name = get_decl_name_string (func_decl); + + /* Duplicate function types are expected to be seen as functions with same + signature will show the same function type. For each distinct function + declaration, however, CTF function type records must be added anew. + Duplicate function *declarations* must, however be avoided. This is + expected to happen if the gen_ctf_function API is called multiple times + for the same func_decl. */ + + bool exists = ctf_type_exists (ctfc, func_decl, &type_id); + gcc_assert (!exists); + + /* Add CTF Function type. */ + type_id = gen_ctf_function_type (ctfc, func_decl, func_name); + + /* Update global functions count. */ + if (TREE_PUBLIC (func_decl)) + ctfc->ctfc_num_global_funcs++; + + return type_id; +} + +/* Add CTF type record(s) for the given input type. */ +static ctf_id_t +gen_ctf_type (ctf_container_ref ctfc, tree type) +{ + ctf_id_t type_id = CTF_NULL_TYPEID; + + /* This API expects to handle tcc_type nodes only. + ctf_add_int/float etc == type == INTEGER_TYPE, REAL_TYPE etc + ctf_add_pointer == type == POINTER_TYPE + ctf_add_array == type == ARRAY_TYPE + ctf_add_sou == type == RECORD_TYPE, UNION_TYPE. */ + gcc_assert (TREE_CODE_CLASS (TREE_CODE (type)) == tcc_type); + + int cvr_quals = get_cvr_quals_for_type (type); + + /* For a type of ARRAY_TYPE, type qualifiers (if any) are with + TREE_TYPE (type). TYPE_MAIN_VARIANT (type) however will not contain + these quals. Need to pass the former to gen_ctf_array_type. */ + tree gen_type = (TREE_CODE (type) == ARRAY_TYPE) + ? type : TYPE_MAIN_VARIANT (type); + + /* CTF type de-duplication in the compiler. */ + if (!ctf_type_exists (ctfc, gen_type, &type_id)) + { + /* Encountering a CTF type for the first time. Add the CTF type. */ + + if (is_ctf_base_type (gen_type)) + type_id = gen_ctf_base_type (ctfc, gen_type); + + else if (RECORD_OR_UNION_TYPE_P (gen_type)) + type_id = gen_ctf_sou_type (ctfc, gen_type); + + else if (TREE_CODE (gen_type) == ARRAY_TYPE) + type_id = gen_ctf_array_type (tu_ctfc, gen_type); + + else if (TREE_CODE (gen_type) == ENUMERAL_TYPE) + type_id = gen_ctf_enum_type (tu_ctfc, gen_type); + + else if (POINTER_TYPE_P (gen_type)) + type_id = gen_ctf_pointer_type (tu_ctfc, gen_type); + + else if (TREE_CODE (gen_type) == FUNCTION_TYPE) + /* Function pointers. */ + type_id = gen_ctf_function_type (tu_ctfc, gen_type, NULL); + + else if (TREE_CODE (gen_type) == VECTOR_TYPE) + /* CTF does not have representation for vector types. Skip this type. + FIXME- Note this TBD_CTF_REPRESENTATION_LIMIT. */ + ; + + else + /* No other type is expected for C frontend. */ + gcc_unreachable (); + } + + /* Add qualifiers if any. */ + if ((type_id != CTF_NULL_TYPEID) && (cvr_quals & ctf_cvr_qual_mask)) + type_id = gen_ctf_cvrquals (ctfc, type, type_id); + + return type_id; +} + +/* Generate CTF records for bitfield declarations. */ + +static ctf_id_t +gen_ctf_bitfield_type_for_decl (ctf_container_ref ctfc, const tree field, + const ctf_id_t type_id) +{ + ctf_id_t bitfield_type_id = CTF_NULL_TYPEID; + + gcc_assert (TREE_CODE (field) == FIELD_DECL); + + gcc_assert (ctfc); + HOST_WIDE_INT size_in_bits = tree_to_shwi (DECL_SIZE (field)); + + ctf_encoding_t ep = {0,0,0}; + /* Assume default encoding as unsigned. */ + uint32_t encoding = 0; + tree type = TREE_TYPE (field); + + if (TREE_CODE (type) == INTEGER_TYPE) + { + /* Handle both enum bitfields and integer bitfields. */ + if (TYPE_STRING_FLAG (type)) + { + if (TYPE_UNSIGNED (type)) + encoding = CTF_INT_CHAR; + else + encoding = CTF_INT_CHAR | CTF_INT_SIGNED; + } + else if (!TYPE_UNSIGNED (type)) + encoding = CTF_INT_SIGNED; + } + else if (TREE_CODE (type) == BOOLEAN_TYPE) + encoding = CTF_INT_BOOL; + else + /* The type of a bit field can be integral or boolean. */ + gcc_unreachable (); + + ep.cte_format = encoding; + /* The offset of the slice is the offset into a machine word. + TBD Handle big-endian - should the offset be byte-order dependent ? */ + ep.cte_offset = int_bit_position (field) % BITS_PER_WORD; + ep.cte_bits = size_in_bits; + + /* No type de-duplication for slices. + (Probe the CTF container with field_decl) + There is no way to de-duplicate two bitfields using just type or decl + references as dtd_key_decl. Two field declarations may share the + same TREE_TYPE and DECL_BIT_FIELD_TYPE references, but may have different + offset and num bits. */ + + bitfield_type_id = ctf_add_slice (ctfc, CTF_ADD_NONROOT, type_id, &ep, + field); + + return bitfield_type_id; +} + +static ctf_id_t +gen_ctf_type_for_decl (ctf_container_ref ctfc, tree decl) +{ + gcc_assert (TREE_CODE_CLASS (TREE_CODE (decl)) == tcc_declaration); + + ctf_id_t type_id = CTF_NULL_TYPEID; + tree type; + tree bitfield_type = NULL; + + type = TREE_TYPE (decl); + + /* In a FIELD_DECL, this indicates whether the field was a bitfield. */ + if (TREE_CODE (decl) == FIELD_DECL) + bitfield_type = DECL_BIT_FIELD_TYPE (decl); + + /* Create CTF for the unqualified type, if it not done already. If it's a + bitfield type, use that to generate the CTF type record. */ + if (bitfield_type) + type = bitfield_type; + + /* CTF type de-duplication in the compiler. + Lookup if CTF for unqualified type has already been added. CTF slices are + not shared across declarations. */ + if (ctf_type_exists (ctfc, type, &type_id)) + { + if (!bitfield_type) + return type_id; + } + else + type_id = gen_ctf_type (ctfc, type); + + /* Now, create CTF slice if it is a bitfield. */ + if (bitfield_type) + type_id = gen_ctf_bitfield_type_for_decl (ctfc, decl, type_id); + + return type_id; +} + +/* Routines for CTF pre-processing. */ + +static void +ctf_preprocess_var (ctf_container_ref ctfc, ctf_dvdef_ref var) +{ + /* Add it to the list of types. This array of types will be sorted before + assembling into output. */ + list_add_ctf_vars (ctfc, var); +} + +/* CTF preprocess callback routine for CTF variables. */ + +bool +ctf_dvd_preprocess_cb (tree const & ARG_UNUSED (key), ctf_dvdef_ref * slot, + void * arg) +{ + tree var_decl; + + ctf_dvd_preprocess_arg_t * dvd_arg = (ctf_dvd_preprocess_arg_t *)arg; + ctf_dvdef_ref var = (ctf_dvdef_ref) *slot; + ctf_container_ref arg_ctfc = dvd_arg->dvd_arg_ctfc; + + ctf_preprocess_var (arg_ctfc, var); + + /* Keep track of global objts. */ + var_decl = var->dvd_decl; + if ((TREE_CODE_CLASS (TREE_CODE (var_decl)) == tcc_declaration) + && TREE_PUBLIC (var_decl)) + { + arg_ctfc->ctfc_gobjts_list[dvd_arg->dvd_global_obj_idx] = var; + dvd_arg->dvd_global_obj_idx++; + } + + return 1; +} + +/* CTF preprocess callback routine for CTF types. */ + +bool +ctf_dtd_preprocess_cb (ctf_dtdef_ref const & ARG_UNUSED (key), + ctf_dtdef_ref * slot, void * arg) +{ + uint32_t kind, vlen; + tree func_decl; + + ctf_dtdef_ref ctftype = (ctf_dtdef_ref) *slot; + ctf_dtd_preprocess_arg_t * dtd_arg = (ctf_dtd_preprocess_arg_t *)arg; + ctf_container_ref arg_ctfc = dtd_arg->dtd_arg_ctfc; + + size_t index = ctftype->dtd_type; + gcc_assert (index <= arg_ctfc->ctfc_types->elements ()); + + /* CTF types need to be output in the order of their type IDs. In other + words, if type A is used to define type B, type ID of type A must + appear before type ID of type B. */ + arg_ctfc->ctfc_types_list[index] = ctftype; + + /* Keep track of the CTF type if it's a function type. */ + kind = CTF_V2_INFO_KIND (ctftype->dtd_data.ctti_info); + if (kind == CTF_K_FUNCTION) + { + func_decl = ctftype->dtd_decl; + if ((TREE_CODE_CLASS (TREE_CODE (func_decl)) == tcc_declaration) + && TREE_PUBLIC (func_decl)) + { + arg_ctfc->ctfc_gfuncs_list[dtd_arg->dtd_global_func_idx] = ctftype; + dtd_arg->dtd_global_func_idx++; + vlen = CTF_V2_INFO_VLEN (ctftype->dtd_data.ctti_info); + /* Update the function info section size in bytes. Avoid using + ctf_calc_num_vbytes API, the latter is only meant to convey + the vlen bytes after CTF types in the CTF data types section. */ + arg_ctfc->ctfc_num_funcinfo_bytes += (vlen + 2) * sizeof (uint32_t); + } + } + + /* Calculate the vlen bytes. */ + arg_ctfc->ctfc_num_vlen_bytes += ctf_calc_num_vbytes (ctftype); + + return 1; +} + +/* CTF preprocessing. + After the CTF types for the compilation unit have been generated fully, the + compiler writes out the asm for the CTF types. + + CTF writeout in the compiler requires two passes over the CTF types. In the + first pass, the CTF preprocess pass: + 1. CTF types are sorted in the order of their type IDs. + 2. The variable number of bytes after each CTF type record are calculated. + This is used to calculate the offsets in the ctf_header_t. + 3. If the CTF type is of CTF_K_FUNCTION, the number of bytes in the + funcinfo sub-section are calculated. This is used to calculate the + offsets in the ctf_header_t. + 4. Keep the list of CTF variables in ASCIIbetical order of their names. + + In the second pass, the CTF writeout pass, asm tags are written out using + the compiler's afore-generated internal pre-processed CTF types. */ + +static void +ctf_preprocess (ctf_container_ref ctfc) +{ + size_t num_ctf_types = ctfc->ctfc_types->elements (); + + /* Initialize an array to keep track of the CTF variables at global + scope. */ + size_t num_global_objts = ctfc->ctfc_num_global_objts; + if (num_global_objts) + { + ctfc->ctfc_gobjts_list = ggc_vec_alloc(num_global_objts); + gcc_assert (num_ctf_types); + } + + size_t num_ctf_vars = ctfc->ctfc_vars->elements (); + if (num_ctf_vars) + { + ctf_dvd_preprocess_arg_t dvd_arg; + dvd_arg.dvd_global_obj_idx = 0; + dvd_arg.dvd_arg_ctfc = ctfc; + + /* Allocate CTF var list. */ + ctfc->ctfc_vars_list = ggc_vec_alloc(num_ctf_vars); + /* Variables appear in the sort ASCIIbetical order of their names. This + permits binary searching in the CTF reader. Add the variables to a + list for sorting. */ + ctfc->ctfc_vars->traverse (&dvd_arg); + /* Sort the list. */ + qsort (ctfc->ctfc_vars_list, num_ctf_vars, sizeof (ctf_dvdef_ref), + ctf_varent_compare); + } + + /* Initialize an array to keep track of the CTF functions types for global + functions in the CTF data section. */ + size_t num_global_funcs = ctfc->ctfc_num_global_funcs; + if (num_global_funcs) + { + ctfc->ctfc_gfuncs_list = ggc_vec_alloc(num_global_funcs); + gcc_assert (num_ctf_types); + } + + if (num_ctf_types) + { + ctf_dtd_preprocess_arg_t dtd_arg; + dtd_arg.dtd_global_func_idx = 0; + dtd_arg.dtd_arg_ctfc = tu_ctfc; + /* Allocate the CTF types list. Add 1 because type ID 0 is never a valid + CTF type ID. No CTF type record should appear at that offset, this + eases debugging and readability. */ + ctfc->ctfc_types_list = ggc_vec_alloc(num_ctf_types + 1); + /* Pre-process CTF types. */ + ctfc->ctfc_types->traverse (&dtd_arg); + + gcc_assert (dtd_arg.dtd_global_func_idx == num_global_funcs); + } +} + +/* CTF asm helper routines. */ + +/* Asm'out the CTF preamble. */ + +static void +ctf_asm_preamble (ctf_container_ref ctfc) +{ + dw2_asm_output_data (2, ctfc->ctfc_magic, + "CTF preamble magic number"); + dw2_asm_output_data (1, ctfc->ctfc_version, "CTF preamble version"); + dw2_asm_output_data (1, ctfc->ctfc_flags, "CTF preamble flags"); +} + +static void +ctf_asm_stype (ctf_dtdef_ref type) +{ + dw2_asm_output_data (4, type->dtd_data.ctti_name, "ctt_name"); + dw2_asm_output_data (4, type->dtd_data.ctti_info, "ctt_info"); + /* union. */ + dw2_asm_output_data (4, type->dtd_data.ctti_size, "ctt_size or ctt_type"); +} + +static void +ctf_asm_type (ctf_dtdef_ref type) +{ + dw2_asm_output_data (4, type->dtd_data.ctti_name, "ctt_name"); + dw2_asm_output_data (4, type->dtd_data.ctti_info, "ctt_info"); + /* union. */ + dw2_asm_output_data (4, type->dtd_data.ctti_size, "ctt_size"); + dw2_asm_output_data (4, type->dtd_data.ctti_lsizehi, "ctt_lsizehi"); + dw2_asm_output_data (4, type->dtd_data.ctti_lsizelo, "ctt_lsizelo"); +} + +static void +ctf_asm_slice (ctf_dtdef_ref type) +{ + dw2_asm_output_data (4, type->dtd_u.dtu_slice.cts_type, "cts_type"); + dw2_asm_output_data (2, type->dtd_u.dtu_slice.cts_offset, "cts_offset"); + dw2_asm_output_data (2, type->dtd_u.dtu_slice.cts_bits, "cts_bits"); +} + +static void +ctf_asm_array (ctf_dtdef_ref dtd) +{ + dw2_asm_output_data (4, dtd->dtd_u.dtu_arr.ctr_contents, "cta_contents"); + dw2_asm_output_data (4, dtd->dtd_u.dtu_arr.ctr_index, "cta_index"); + dw2_asm_output_data (4, dtd->dtd_u.dtu_arr.ctr_nelems, "cta_nelems"); +} + +static void +ctf_asm_varent (ctf_dvdef_ref var) +{ + /* Output the reference to the name in the string table. */ + dw2_asm_output_data (4, var->dvd_name_offset, "ctv_name"); + /* Output the type index. */ + dw2_asm_output_data (4, var->dvd_type, "ctv_typeidx"); +} + +static void +ctf_asm_sou_lmember (ctf_dmdef_t * dmd) +{ + dw2_asm_output_data (4, dmd->dmd_name_offset, "ctlm_name"); + dw2_asm_output_data (4, CTF_OFFSET_TO_LMEMHI (dmd->dmd_offset), + "ctlm_offsethi"); + dw2_asm_output_data (4, dmd->dmd_type, "ctlm_type"); + dw2_asm_output_data (4, CTF_OFFSET_TO_LMEMLO (dmd->dmd_offset), + "ctlm_offsetlo"); +} + +static void +ctf_asm_sou_member (ctf_dmdef_t * dmd) +{ + dw2_asm_output_data (4, dmd->dmd_name_offset, "ctm_name"); + dw2_asm_output_data (4, dmd->dmd_offset, "ctm_offset"); + dw2_asm_output_data (4, dmd->dmd_type, "ctm_type"); +} + +static void +ctf_asm_enum_const (ctf_dmdef_t * dmd) +{ + dw2_asm_output_data (4, dmd->dmd_name_offset, "cte_name"); + dw2_asm_output_data (4, dmd->dmd_value, "cte_value"); +} + +/* CTF writeout to asm file. */ + +static void +output_ctf_header (ctf_container_ref ctfc) +{ + switch_to_section (ctf_info_section); + ASM_OUTPUT_LABEL (asm_out_file, ctf_info_section_label); + + ctf_asm_preamble (ctfc); + + /* For a single compilation unit, the parent container's name and label are + NULL. */ + dw2_asm_output_data (4, 0, "cth_parlabel"); + dw2_asm_output_data (4, 0, "cth_parname"); + dw2_asm_output_data (4, ctfc->ctfc_cuname_offset, "cth_cuname"); + + int typeslen = 0; + /* Initialize the offsets. The offsets are from after the CTF header. */ + uint32_t lbloff = 0; + uint32_t objtoff = 0; + uint32_t funcoff = 0; + uint32_t objtidxoff = 0; + uint32_t funcidxoff = 0; + uint32_t varoff = 0; + uint32_t typeoff = 0; + uint32_t stroff = 0; + + if (! is_empty_container (ctfc)) + { + gcc_assert (get_num_ctf_types (ctfc) + == (ctfc->ctfc_num_types + ctfc->ctfc_num_stypes)); + + funcoff = objtoff + ctfc->ctfc_num_global_objts * sizeof (uint32_t); + /* Object index appears after function info. */ + objtidxoff = funcoff + get_ctfc_num_funcinfo_bytes (ctfc); + /* Funxtion index goes next. */ + funcidxoff = objtidxoff + ctfc->ctfc_num_global_objts * sizeof (uint32_t); + /* Vars appear after function index. */ + varoff = funcidxoff + ctfc->ctfc_num_global_funcs * sizeof (uint32_t); + /* CTF types appear after vars. */ + typeoff = varoff + get_num_ctf_vars (ctfc) * sizeof (ctf_varent_t); + /* The total number of bytes for CTF types is the sum of the number of + times struct ctf_type_t, struct ctf_stype_t are written, plus the + amount of variable length data after each one of these. */ + typeslen = ctfc->ctfc_num_types * sizeof (ctf_type_t) + + ctfc->ctfc_num_stypes * (sizeof (ctf_stype_t)) + + get_ctfc_num_vlen_bytes (ctfc); + + /* Strings appear after types. */ + stroff = typeoff + typeslen; + } + + /* Offset of label section. */ + dw2_asm_output_data (4, lbloff, "cth_lbloff"); + /* Offset of object section. */ + dw2_asm_output_data (4, objtoff, "cth_objtoff"); + /* Offset of function section. */ + dw2_asm_output_data (4, funcoff, "cth_funcoff"); + /* Offset of object index section. */ + dw2_asm_output_data (4, objtidxoff, "cth_objtidxoff"); + /* Offset of function index section. */ + dw2_asm_output_data (4, funcidxoff, "cth_funcidxoff"); + + /* Offset of variable section. */ + dw2_asm_output_data (4, varoff, "cth_varoff"); + /* Offset of type section. */ + dw2_asm_output_data (4, typeoff, "cth_typeoff"); + /* Offset of string section. */ + dw2_asm_output_data (4, stroff, "cth_stroff"); + /* Length of string section in bytes. */ + dw2_asm_output_data (4, ctfc->ctfc_strlen, "cth_strlen"); +} + +static void +output_ctf_obj_info (ctf_container_ref ctfc) +{ + unsigned long i; + ctf_dvdef_ref var; + + if (!ctfc->ctfc_num_global_objts) return; + + /* Compiler spits out the objts (at global scope) in the CTF obj info section. + In no specific order. In an object file, the CTF object index section is + used to associate the objts to their corresponding names. */ + for (i = 0; i < ctfc->ctfc_num_global_objts; i++) + { + var = ctfc->ctfc_gobjts_list[i]; + + /* CTF type ID corresponding to the type of the variable. */ + dw2_asm_output_data (4, var->dvd_type, "objtinfo_var_type"); + } + +} + +static void +output_ctf_func_info (ctf_container_ref ctfc) +{ + unsigned long i, j; + ctf_dtdef_ref ctftype; + uint32_t vlen; + + if (!ctfc->ctfc_num_global_funcs) return; + + /* Compiler spits out the function type, return type, and args of each global + function in the CTF funcinfo section. In no specific order. + In an object file, the CTF function index section is used to associate + functions to their corresponding names. */ + for (i = 0; i < ctfc->ctfc_num_global_funcs; i++) + { + ctftype = ctfc->ctfc_gfuncs_list[i]; + vlen = CTF_V2_INFO_VLEN (ctftype->dtd_data.ctti_info); + + /* function type. */ + dw2_asm_output_data (4, ctftype->dtd_type, "funcinfo_func_type"); + + /* return type. */ + dw2_asm_output_data (4, ctftype->dtd_data.ctti_type, + "funcinfo_func_return_type"); + + /* function args types. */ + for (j = 0; j < vlen; j++) + dw2_asm_output_data (4, ctftype->dtd_u.dtu_argv[j].farg_type, + "funcinfo_func_args"); + } +} + +static void +output_ctf_objtidx (ctf_container_ref ctfc) +{ + unsigned long i; + ctf_dvdef_ref var; + + if (!ctfc->ctfc_num_global_objts) return; + + for (i = 0; i < ctfc->ctfc_num_global_objts; i++) + { + var = ctfc->ctfc_gobjts_list[i]; + /* Offset to the name in CTF string table. */ + dw2_asm_output_data (4, var->dvd_name_offset, "objtinfo_name"); + } +} + +static void +output_ctf_funcidx (ctf_container_ref ctfc) +{ + unsigned long i; + ctf_dtdef_ref ctftype; + + if (!ctfc->ctfc_num_global_funcs) return; + + for (i = 0; i < ctfc->ctfc_num_global_funcs; i++) + { + ctftype = ctfc->ctfc_gfuncs_list[i]; + /* Offset to the name in CTF string table. */ + dw2_asm_output_data (4, ctftype->dtd_data.ctti_name, "funcinfo_name"); + } +} + +/* Output the CTF variables. Variables appear in the sort ASCIIbetical order + of their names. This permits binary searching in the CTF reader. */ + +static void +output_ctf_vars (ctf_container_ref ctfc) +{ + size_t i; + size_t num_ctf_vars = ctfc->ctfc_vars->elements (); + if (num_ctf_vars) + { + /* Iterate over the list of sorted vars and output the asm. */ + for (i = 0; i < num_ctf_vars; i++) + ctf_asm_varent (ctfc->ctfc_vars_list[i]); + } +} + +/* Output the CTF string records. */ + +static void +output_ctf_strs (ctf_container_ref ctfc) +{ + ctf_string_t * ctf_string = ctfc->ctfc_strtable.ctstab_head; + + while (ctf_string) + { + dw2_asm_output_nstring (ctf_string->cts_str, -1, "ctf_string"); + ctf_string = ctf_string->cts_next; + } +} + +static void +output_asm_ctf_sou_fields (ctf_container_ref ARG_UNUSED (ctfc), + ctf_dtdef_ref dtd) +{ + ctf_dmdef_t * dmd; + + /* Function pointer to dump struct/union members. */ + void (*ctf_asm_sou_field_func) (ctf_dmdef_t *); + + uint32_t size = dtd->dtd_data.ctti_size; + + /* The variable length data struct/union CTF types is an array of + ctf_member or ctf_lmember, depending on size of the member. */ + if (size >= CTF_LSTRUCT_THRESH) + ctf_asm_sou_field_func = ctf_asm_sou_lmember; + else + ctf_asm_sou_field_func = ctf_asm_sou_member; + + for (dmd = dtd->dtd_u.dtu_members; + dmd != NULL; dmd = (ctf_dmdef_t *) ctf_dmd_list_next (dmd)) + ctf_asm_sou_field_func (dmd); +} + +static void +output_asm_ctf_enum_list (ctf_container_ref ARG_UNUSED (ctfc), + ctf_dtdef_ref dtd) +{ + ctf_dmdef_t * dmd; + + for (dmd = dtd->dtd_u.dtu_members; + dmd != NULL; dmd = (ctf_dmdef_t *) ctf_dmd_list_next (dmd)) + ctf_asm_enum_const (dmd); +} + +static void +output_asm_ctf_vlen_bytes (ctf_container_ref ctfc, ctf_dtdef_ref ctftype) +{ + uint32_t encoding; + uint32_t kind = CTF_V2_INFO_KIND (ctftype->dtd_data.ctti_info); + uint32_t vlen = CTF_V2_INFO_VLEN (ctftype->dtd_data.ctti_info); + uint32_t i; + + switch (kind) + { + case CTF_K_INTEGER: + case CTF_K_FLOAT: + if (kind == CTF_K_INTEGER) + { + encoding = CTF_INT_DATA (ctftype->dtd_u.dtu_enc.cte_format, + ctftype->dtd_u.dtu_enc.cte_offset, + ctftype->dtd_u.dtu_enc.cte_bits); + } + else + { + encoding = CTF_FP_DATA (ctftype->dtd_u.dtu_enc.cte_format, + ctftype->dtd_u.dtu_enc.cte_offset, + ctftype->dtd_u.dtu_enc.cte_bits); + } + dw2_asm_output_data (4, encoding, "ctf_encoding_data"); + break; + case CTF_K_FUNCTION: + { + for (i = 0; i < vlen; i++) + dw2_asm_output_data (4, ctftype->dtd_u.dtu_argv[i].farg_type, + "dtu_argv"); + /* FIXME - CTF_PADDING_FOR_ALIGNMENT. + libctf expects this padding for alignment reasons. Expected to + be redundant in CTF_VERSION_4. */ + if (vlen & 1) + dw2_asm_output_data (4, 0, "dtu_argv_padding"); + + break; + } + case CTF_K_ARRAY: + ctf_asm_array (ctftype); + break; + case CTF_K_SLICE: + ctf_asm_slice (ctftype); + break; + + case CTF_K_STRUCT: + case CTF_K_UNION: + output_asm_ctf_sou_fields (ctfc, ctftype); + break; + case CTF_K_ENUM: + output_asm_ctf_enum_list (ctfc, ctftype); + break; + + default: + /* CTF types of kind CTF_K_VOLATILE, CTF_K_CONST, CTF_K_RESTRICT, + etc have no vlen data to write. */ + break; + } +} + +static void +output_asm_ctf_type (ctf_container_ref ctfc, ctf_dtdef_ref type) +{ + if (type->dtd_data.ctti_size <= CTF_MAX_SIZE) + ctf_asm_stype (type); + else + ctf_asm_type (type); + /* Now comes the variable-length portion for defining types completely. + E.g., encoding follows CTF_INT_DATA, CTF_FP_DATA types, + struct ctf_array_t follows CTF_K_ARRAY types, or a bunch of + struct ctf_member / ctf_lmember ctf_enum sit in there for CTF_K_STRUCT or + CTF_K_UNION. */ + output_asm_ctf_vlen_bytes (ctfc, type); +} + +/* Output the CTF type records. */ + +static void +output_ctf_types (ctf_container_ref ctfc) +{ + size_t i; + size_t num_ctf_types = ctfc->ctfc_types->elements (); + if (num_ctf_types) + { + /* Type ID = 0 is used as sentinel value; not a valid type. */ + for (i = 1; i <= num_ctf_types; i++) + output_asm_ctf_type (ctfc, ctfc->ctfc_types_list[i]); + } +} + +static void +ctf_decl (tree decl) +{ + switch (TREE_CODE (decl)) + { + case ERROR_MARK: + return; + + case FUNCTION_DECL: + gen_ctf_function (tu_ctfc, decl); + break; + + case VAR_DECL: + gen_ctf_variable (tu_ctfc, decl); + break; + + case TYPE_DECL: + /* Stay aligned to what DWARF does. + DWARF has this check so as to not emit stubs for types unless they are + needed by other DIEs. */ + if (TYPE_DECL_SUPPRESS_DEBUG (decl)) + return; + + if (DECL_IS_BUILTIN (decl)) + return; + + /* If we are in terse mode, don't generate any CTF for types. */ + if (ctf_debug_info_level <= CTFINFO_LEVEL_TERSE) + return; + /* If function-scope tag, do not generate CTF type info for it. */ + if (decl_function_context (decl)) + return; + + gen_ctf_typedef (tu_ctfc, decl); + + break; + + default: + if (TREE_CODE (decl) != PARM_DECL) + /* FIXME - Its not clear why PARM_DECL arise here. */ + /* No other TREE_CODE is expected at this time. */ + gcc_unreachable (); + } +} + +/* CTF routines interfacing to the compiler. */ + +void +ctf_debug_init (void) +{ + init_ctf_containers (); +} + +void +ctf_early_finish (const char * filename) +{ + if (ctf_debug_info_level == CTFINFO_LEVEL_NONE) + return; + + init_ctf_sections (); + + ctfc_add_cuname (tu_ctfc, filename); + + /* Pre-process CTF before generating assembly. */ + ctf_preprocess (tu_ctfc); + + output_ctf_header (tu_ctfc); + output_ctf_obj_info (tu_ctfc); + output_ctf_func_info (tu_ctfc); + output_ctf_objtidx (tu_ctfc); + output_ctf_funcidx (tu_ctfc); + output_ctf_vars (tu_ctfc); + output_ctf_types (tu_ctfc); + output_ctf_strs (tu_ctfc); + + /* The total number of string bytes must be equal to those processed out to + the str subsection. */ + gcc_assert (tu_ctfc->ctfc_strlen == get_cur_ctf_str_len (tu_ctfc)); + + delete_ctf_container (tu_ctfc); +} + +void +ctf_early_global_decl (tree decl) +{ + /* Generate CTF type information if appropriate debug level is set + to CTFINFO_LEVEL_NORMAL. */ + + if (ctf_debug_info_level == CTFINFO_LEVEL_NORMAL) + ctf_decl (decl); } /* Reset all state within ctfout.c so that we can rerun the compiler @@ -170,6 +1935,7 @@ ctfout_c_finalize (void) ctf_info_section = NULL; delete_ctf_container (tu_ctfc); + tu_ctfc = NULL; } #include "gt-ctfout.h" diff --git a/gcc/ctfout.h b/gcc/ctfout.h index f281aaf..6a01f82 100644 --- a/gcc/ctfout.h +++ b/gcc/ctfout.h @@ -24,10 +24,189 @@ along with GCC; see the file COPYING3. If not see #ifndef GCC_CTFOUT_H #define GCC_CTFOUT_H 1 +#include "config.h" +#include "system.h" +#include "tree.h" +#include "fold-const.h" +#include "tree-hash-traits.h" #include "ctf.h" +/* Invalid CTF type ID definition. */ + +#define CTF_NULL_TYPEID 0 + +/* Value to start generating the CTF type ID from. */ + +#define CTF_INIT_TYPEID 1 + +/* CTF type ID. */ + +typedef unsigned long ctf_id_t; + +/* CTF string table element (list node). */ + +typedef struct GTY ((chain_next ("%h.cts_next"))) ctf_string +{ + const char * cts_str; /* CTF string. */ + struct ctf_string * cts_next; /* A list node. */ +} ctf_string_t; + +/* Internal representation of CTF string table. */ + +typedef struct GTY (()) ctf_strtable +{ + ctf_string_t * ctstab_head; /* Head str ptr. */ + ctf_string_t * ctstab_tail; /* Tail. new str appended to tail. */ + int ctstab_num; /* Number of strings in the table. */ + size_t ctstab_len; /* Size of string table in bytes. */ + const char * ctstab_estr; /* Empty string "". */ +} ctf_strtable_t; + +/* Encoding information for integers, floating-point values etc. The flags + field will contain values appropriate for the type defined in . */ + +typedef struct GTY (()) ctf_encoding +{ + unsigned int cte_format; /* Data format (CTF_INT_* or CTF_FP_* flags). */ + unsigned int cte_offset; /* Offset of value in bits. */ + unsigned int cte_bits; /* Size of storage in bits. */ +} ctf_encoding_t; + +/* Array information for CTF generation. */ + +typedef struct GTY (()) ctf_arinfo +{ + ctf_id_t ctr_contents; /* Type of array contents. */ + ctf_id_t ctr_index; /* Type of array index. */ + unsigned int ctr_nelems; /* Number of elements. */ +} ctf_arinfo_t; + +/* Function information for CTF generation. */ + +typedef struct GTY (()) ctf_funcinfo +{ + ctf_id_t ctc_return; /* Function return type. */ + unsigned int ctc_argc; /* Number of typed arguments to function. */ + unsigned int ctc_flags; /* Function attributes (see below). */ +} ctf_funcinfo_t; + +typedef struct GTY (()) ctf_sliceinfo +{ + unsigned int cts_type; /* Reference CTF type. */ + unsigned short cts_offset; /* Offset in bits of the first bit. */ + unsigned short cts_bits; /* Size in bits. */ +} ctf_sliceinfo_t; + +/* CTF type representation internal to the compiler. It closely reflects the + ctf_type_t type node in except the GTY (()) tags. */ + +typedef struct GTY (()) ctf_itype +{ + unsigned int ctti_name; /* Reference to name in string table. */ + unsigned int ctti_info; /* Encoded kind, variant length (see below). */ + union GTY ((desc ("0"))) + { + unsigned int GTY ((tag ("0"))) _size;/* Size of entire type in bytes. */ + unsigned int GTY ((tag ("1"))) _type;/* Reference to another type. */ + } _u; + unsigned int ctti_lsizehi; /* High 32 bits of type size in bytes. */ + unsigned int ctti_lsizelo; /* Low 32 bits of type size in bytes. */ +} ctf_itype_t; + +#define ctti_size _u._size +#define ctti_type _u._type + +/* Function arguments end with varargs. */ + +#define CTF_FUNC_VARARG 0x1 + +/* Struct/union/enum member definition for CTF generation. */ + +typedef struct GTY ((chain_next ("%h.dmd_next"))) ctf_dmdef +{ + const char * dmd_name; /* Name of this member. */ + ctf_id_t dmd_type; /* Type of this member (for sou). */ + unsigned int dmd_name_offset; /* Offset of the name in str table. */ + unsigned long dmd_offset; /* Offset of this member in bits (for sou). */ + int dmd_value; /* Value of this member (for enum). */ + struct ctf_dmdef * dmd_next; /* A list node. */ +} ctf_dmdef_t; + +/* Function Argument. (Encapsulated because GTY machinery does not like + non struct/union members. See usage in ctf_dtdef_t.) */ + +typedef struct GTY (()) ctf_func_arg +{ + ctf_id_t farg_type; /* Type identifier of the argument. */ +} ctf_func_arg_t; + +typedef struct GTY (()) ctf_dtdef_key +{ + tree dtdk_key_decl; /* Tree decl corresponding to the type. */ + unsigned int dtdk_key_flags; /* Extra flags for hashing the type. */ +} ctf_dtdef_key_t; + +/* Type definition for CTF generation. */ + +typedef struct GTY (()) ctf_dtdef +{ + ctf_dtdef_key_t dtd_key; /* Type key for hashing. */ + const char * dtd_name; /* Name associated with definition (if any). */ + ctf_id_t dtd_type; /* Type identifier for this definition. */ + ctf_itype_t dtd_data; /* Type node. */ + union GTY ((desc ("ctf_dtu_d_union_selector (&%1)"))) + { + /* struct, union, or enum. */ + ctf_dmdef_t * GTY ((tag ("CTF_DTU_D_MEMBERS"))) dtu_members; + /* array. */ + ctf_arinfo_t GTY ((tag ("CTF_DTU_D_ARRAY"))) dtu_arr; + /* integer or float. */ + ctf_encoding_t GTY ((tag ("CTF_DTU_D_ENCODING"))) dtu_enc; + /* function. */ + ctf_func_arg_t * GTY ((tag ("CTF_DTU_D_ARGUMENTS"))) dtu_argv; + /* slice. */ + ctf_sliceinfo_t GTY ((tag ("CTF_DTU_D_SLICE"))) dtu_slice; + } dtd_u; +} ctf_dtdef_t; + +#define dtd_decl dtd_key.dtdk_key_decl +#define dtd_key_flags dtd_key.dtdk_key_flags + +/* Variable definition for CTF generation. */ + +typedef struct GTY (()) ctf_dvdef +{ + tree dvd_decl; /* Tree decl corresponding to the variable. */ + const char * dvd_name; /* Name associated with variable. */ + unsigned int dvd_name_offset; /* Offset of the name in str table. */ + ctf_id_t dvd_type; /* Type of variable. */ +} ctf_dvdef_t; + +typedef ctf_dvdef_t * ctf_dvdef_ref; +typedef ctf_dtdef_t * ctf_dtdef_ref; + +/* Helper enum and api for the GTY machinery to work on union dtu_d. */ + +enum ctf_dtu_d_union_enum { + CTF_DTU_D_MEMBERS, + CTF_DTU_D_ARRAY, + CTF_DTU_D_ENCODING, + CTF_DTU_D_ARGUMENTS, + CTF_DTU_D_SLICE +}; + +enum ctf_dtu_d_union_enum +ctf_dtu_d_union_selector (ctf_dtdef_ref); + +struct ctf_dtdef_hash : ggc_ptr_hash +{ + typedef ctf_dtdef_ref compare_type; + static hashval_t hash (ctf_dtdef_ref); + static bool equal (ctf_dtdef_ref, ctf_dtdef_ref); +}; + /* CTF container structure. - It is the context passed around when generating CTF debug info. There is + It is the context passed around when generating ctf debug info. There is one container per translation unit. */ typedef struct GTY (()) ctf_container @@ -36,12 +215,68 @@ typedef struct GTY (()) ctf_container unsigned short ctfc_magic; unsigned char ctfc_version; unsigned char ctfc_flags; - /* CTF Types. */ - // hash_map * GTY (()) ctfc_types; + unsigned int ctfc_cuname_offset; + + /* CTF types. */ + hash_map * GTY (()) ctfc_types; + /* CTF variables. */ + hash_map * GTY (()) ctfc_vars; + /* CTF string table. */ + ctf_strtable_t ctfc_strtable; + + unsigned long ctfc_num_types; + unsigned long ctfc_num_stypes; + unsigned long ctfc_num_global_funcs; + unsigned long ctfc_num_global_objts; + + unsigned long ctfc_num_funcinfo_bytes; + /* Number of vlen bytes - the variable length portion after ctf_type_t and + ctf_stype_t in the CTF section. This is used to calculate the offsets in + the CTF header. */ + unsigned long ctfc_num_vlen_bytes; + + /* Next CTF type id to assign. */ + ctf_id_t ctfc_nextid; + /* List of pre-processed CTF Variables. CTF requires that the variables + appear in the sorted order of their names. */ + ctf_dvdef_t ** GTY ((length ("%h.ctfc_vars ? %h.ctfc_vars->elements () : 0"))) ctfc_vars_list; + /* List of pre-processed CTF types. CTF requires that a shared type must + appear before the type that uses it. For the compiler, this means types + are emitted in sorted order of their type IDs. */ + ctf_dtdef_t ** GTY ((length ("%h.ctfc_types ? %h.ctfc_types->elements () : 0"))) ctfc_types_list; + /* List of CTF function types for global functions. The order of global + function entries in the CTF funcinfo section is undefined by the + compiler. */ + ctf_dtdef_t ** GTY ((length ("%h.ctfc_num_global_funcs"))) ctfc_gfuncs_list; + /* List of CTF variables at global scope. The order of global object entries + in the CTF objinfo section is undefined by the compiler. */ + ctf_dvdef_t ** GTY ((length ("%h.ctfc_num_global_objts"))) ctfc_gobjts_list; + + /* Following members are for debugging only. They do not add functional + value to the task of CTF creation. These can be cleaned up once CTF + generation stabilizes. */ + + /* Keep a count of the number of bytes dumped in asm for debugging + purposes. */ + unsigned long ctfc_numbytes_asm; + /* Total length of all strings in CTF. */ + size_t ctfc_strlen; + } ctf_container_t; typedef ctf_container_t * ctf_container_ref; +/* If the next ctf type id is still set to the init value, no ctf records to + report. */ +#define is_empty_container(ctfc) (((ctfc)->ctfc_nextid == CTF_INIT_TYPEID)) +#define get_num_ctf_vars(ctfc) (ctfc->ctfc_vars->elements ()) +#define get_num_ctf_types(ctfc) (ctfc->ctfc_types->elements ()) + +#define get_cur_ctf_str_len(ctfc) ((ctfc)->ctfc_strtable.ctstab_len) + +#define get_ctfc_num_vlen_bytes(ctfc) ((ctfc)->ctfc_num_vlen_bytes) +#define get_ctfc_num_funcinfo_bytes(ctfc) ((ctfc)->ctfc_num_funcinfo_bytes) + void ctf_debug_init (void); void ctf_early_global_decl (tree decl); @@ -50,4 +285,80 @@ void ctf_early_finish (const char * filename); void ctfout_c_finalize (void); +/* The compiler demarcates whether types are visible at top-level scope or not. + The only example so far of a type not visible at top-level scope is slices. + CTF_ADD_NONROOT is used to indicate the latter. */ +#define CTF_ADD_NONROOT 0 /* CTF type only visible in nested scope. */ +#define CTF_ADD_ROOT 1 /* CTF type visible at top-level scope. */ + +/* Interface from ctfcreate.c to ctfout.c. + These APIs create CTF types and add them to the CTF container associated + with the translation unit. The return value is the typeID of the CTF type + added to the container. */ +extern ctf_id_t ctf_add_volatile (ctf_container_ref, uint32_t, ctf_id_t, tree, + uint32_t); +extern ctf_id_t ctf_add_const (ctf_container_ref, uint32_t, ctf_id_t, tree, + uint32_t); +extern ctf_id_t ctf_add_restrict (ctf_container_ref, uint32_t, ctf_id_t, tree, + uint32_t); +extern ctf_id_t ctf_add_enum (ctf_container_ref, uint32_t, const char *, + HOST_WIDE_INT, tree); +extern ctf_id_t ctf_add_slice (ctf_container_ref, uint32_t, ctf_id_t, + const ctf_encoding_t *, tree); +extern ctf_id_t ctf_add_float (ctf_container_ref, uint32_t, const char *, + const ctf_encoding_t *, tree); +extern ctf_id_t ctf_add_integer (ctf_container_ref, uint32_t, const char *, + const ctf_encoding_t *, tree); +extern ctf_id_t ctf_add_pointer (ctf_container_ref, uint32_t flag, ctf_id_t, + tree); +extern ctf_id_t ctf_add_array (ctf_container_ref, uint32_t, + const ctf_arinfo_t *, tree); +extern ctf_id_t ctf_add_forward (ctf_container_ref, uint32_t, const char *, + uint32_t, tree); +extern ctf_id_t ctf_add_typedef (ctf_container_ref, uint32_t, const char *, + ctf_id_t, tree); +extern ctf_id_t ctf_add_function (ctf_container_ref, uint32_t, const char *, + const ctf_funcinfo_t *, ctf_func_arg_t *, + tree); +extern ctf_id_t ctf_add_sou (ctf_container_ref, uint32_t, const char *, + uint32_t, size_t, tree); + +extern int ctf_add_enumerator (ctf_container_ref, ctf_id_t, const char *, + HOST_WIDE_INT, tree); +extern int ctf_add_member_offset (ctf_container_ref, tree, const char *, + ctf_id_t, unsigned long); +extern int ctf_add_variable (ctf_container_ref, const char *, ctf_id_t, tree); + +/* Interface from ctfutils.c. + Utility functions for CTF generation. */ + +#define ctf_dmd_list_next(elem) ((ctf_dmdef_t *)((elem)->dmd_next)) + +extern void ctf_dmd_list_append (ctf_dmdef_t **, ctf_dmdef_t *); + +extern void ctf_dtd_insert (ctf_container_ref, ctf_dtdef_ref); +extern void ctf_dtd_delete (ctf_container_ref, ctf_dtdef_ref); +extern ctf_dtdef_ref ctf_dtd_lookup (const ctf_container_ref, const tree); +extern ctf_dtdef_ref ctf_dtd_lookup_with_flags (const ctf_container_ref, + const tree, + const unsigned int); + +extern void ctf_dvd_insert (ctf_container_ref, ctf_dvdef_ref); +extern void ctf_dvd_delete (ctf_container_ref, ctf_dvdef_ref); +extern ctf_dvdef_ref ctf_dvd_lookup (const ctf_container_ref, const tree); + +extern int ctf_varent_compare (const void *, const void *); +extern unsigned long ctf_calc_num_vbytes (ctf_dtdef_ref); + +/* Add a str to the CTF string table. */ +extern const char * ctf_add_string (ctf_container_ref, const char *, + uint32_t *); + +extern void list_add_ctf_vars (ctf_container_ref, ctf_dvdef_ref); + +/* Interface from ctfout.c to ctfutils.c. */ + +extern hashval_t hash_dtd_tree_decl (tree, uint32_t); +extern hashval_t hash_dvd_tree_decl (tree); + #endif /* GCC_CTFOUT_H */ diff --git a/gcc/ctfutils.c b/gcc/ctfutils.c new file mode 100644 index 0000000..805c91f --- /dev/null +++ b/gcc/ctfutils.c @@ -0,0 +1,198 @@ +/* Functions to create and update CTF from GCC. + Copyright (C) 2019 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +. */ + +/* This file contains implementation of various utility functions to collect + and keep CTF information. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "ctfout.h" + +/* Append member definition to the list. Member list is a singly-linked list + with list start pointing to the head. */ + +void +ctf_dmd_list_append (ctf_dmdef_t ** dmd, ctf_dmdef_t * elem) +{ + ctf_dmdef_t * tail = (dmd && *dmd) ? *dmd : NULL; + if (tail) + { + while (tail->dmd_next) + tail = tail->dmd_next; + + tail->dmd_next = elem; + } + else + *dmd = elem; + + elem->dmd_next = NULL; +} + +/* Compare two CTF variable definition entries. Currently used for sorting + by name. */ + +int +ctf_varent_compare (const void * entry1, const void * entry2) +{ + int result; + const ctf_dvdef_t * e1 = *(const ctf_dvdef_t * const*) entry1; + const ctf_dvdef_t * e2 = *(const ctf_dvdef_t * const*) entry2; + + result = strcmp (e1->dvd_name, e2->dvd_name); + + return result; +} + +/* Add str to CTF string table. No de-duplication of CTF strings is done by + the compiler. */ + +static void +ctfc_strtable_add_str (ctf_strtable_t * str_table, const char * str) +{ + ctf_string_t * ctf_string = ggc_cleared_alloc (); + /* Keep a reference to the input STR. */ + ctf_string->cts_str = str; + ctf_string->cts_next = NULL; + + if (!str_table->ctstab_head) + str_table->ctstab_head = ctf_string; + + /* Append to the end of the list. */ + if (str_table->ctstab_tail) + str_table->ctstab_tail->cts_next = ctf_string; + + str_table->ctstab_tail = ctf_string; +} + +const char * +ctf_add_string (ctf_container_ref ctfc, const char * name, + uint32_t * name_offset) +{ + size_t len; + char * ctf_string; + /* Return value is the offset to the string in the string table. */ + uint32_t str_offset = get_cur_ctf_str_len (ctfc); + + /* Add empty string only once at the beginning of the string table. Also, do + not add null strings, return the offset to the empty string for them. */ + if ((!name || (name != NULL && !strcmp (name, ""))) && str_offset) + { + ctf_string = CONST_CAST (char *, ctfc->ctfc_strtable.ctstab_estr); + str_offset = 0; + } + else + { + gcc_assert (name); + /* Add null-terminated strings to the string table. */ + len = strlen (name) + 1; + ctf_string = CONST_CAST (char *, ggc_strdup (name)); + + ctfc_strtable_add_str (&(ctfc->ctfc_strtable), ctf_string); + /* Add string to the string table. Keep number of strings updated. */ + ctfc->ctfc_strtable.ctstab_num++; + /* Keep the number of bytes contained in the CTF string table updated. */ + (ctfc)->ctfc_strtable.ctstab_len += len; + } + + *name_offset = str_offset; + + return (const char *) ctf_string; +} + +/* A CTF type record may be followed by variable-length of bytes to encode the + CTF type completely. This routine calculates the number of bytes, in the + final binary CTF format, which are used to encode information about the type + completely. + + This function must always be in sync with the CTF header. */ + +unsigned long +ctf_calc_num_vbytes (ctf_dtdef_ref ctftype) +{ + uint32_t size; + unsigned long vlen_bytes = 0; + + uint32_t kind = CTF_V2_INFO_KIND (ctftype->dtd_data.ctti_info); + uint32_t vlen = CTF_V2_INFO_VLEN (ctftype->dtd_data.ctti_info); + + ctf_dmdef_t * dmd; + uint32_t size_per_member = 0; + unsigned int num_members = 0; + + switch (kind) + { + case CTF_K_FORWARD: + case CTF_K_UNKNOWN: + case CTF_K_POINTER: + case CTF_K_TYPEDEF: + case CTF_K_VOLATILE: + case CTF_K_CONST: + case CTF_K_RESTRICT: + /* These types have no vlen data. */ + break; + + case CTF_K_INTEGER: + case CTF_K_FLOAT: + /* 4 bytes to represent encoding CTF_INT_DATA, CTF_FP_DATA. */ + vlen_bytes += sizeof (uint32_t); + break; + case CTF_K_FUNCTION: + /* FIXME - CTF_PADDING_FOR_ALIGNMENT. */ + vlen_bytes += (vlen + (vlen & 1)) * sizeof (uint32_t); + break; + case CTF_K_ARRAY: + /* This has a single ctf_array_t. */ + vlen_bytes += sizeof (ctf_array_t); + break; + case CTF_K_SLICE: + vlen_bytes += sizeof (ctf_slice_t); + break; + case CTF_K_STRUCT: + case CTF_K_UNION: + /* Count the number and type of members. */ + size = ctftype->dtd_data.ctti_size; + size_per_member = size >= CTF_LSTRUCT_THRESH + ? sizeof (ctf_lmember_t) : sizeof (ctf_member_t); + + /* Sanity check - number of members of struct must be the same as + vlen. */ + for (dmd = ctftype->dtd_u.dtu_members; + dmd != NULL; dmd = (ctf_dmdef_t *) ctf_dmd_list_next (dmd)) + num_members++; + gcc_assert (vlen == num_members); + + vlen_bytes += (num_members * size_per_member); + break; + case CTF_K_ENUM: + vlen_bytes += vlen * sizeof (ctf_enum_t); + break; + default : + break; + } + return vlen_bytes; +} + +void +list_add_ctf_vars (ctf_container_ref ctfc, ctf_dvdef_ref var) +{ + /* FIXME - static may not fly with multiple CUs. */ + static int num_vars_added = 0; + ctfc->ctfc_vars_list[num_vars_added++] = var; +} diff --git a/include/ctf.h b/include/ctf.h index 3a6f266..afc6e8f 100644 --- a/include/ctf.h +++ b/include/ctf.h @@ -52,10 +52,15 @@ extern "C" The CTF file or section itself has the following structure: - +--------+--------+---------+----------+----------+-------+--------+ - | file | type | data | function | variable | data | string | - | header | labels | objects | info | info | types | table | - +--------+--------+---------+----------+----------+-------+--------+ + +--------+--------+---------+----------+--------+----------+... + | file | type | data | function | object | function |... + | header | labels | objects | info | index | index |... + +--------+--------+---------+----------+--------+----------+... + + ...+----------+-------+--------+ + ...| variable | data | string | + ...| info | types | table | + +----------+-------+--------+ The file header stores a magic number and version information, encoding flags, and the byte offset of each of the sections relative to the end of the @@ -74,14 +79,27 @@ extern "C" For each data object, the type ID (a small integer) is recorded. For each function, the type ID of the return type and argument types is recorded. + For situations in which the order of the symbols in the symtab is not known, + a pair of optional indexes follow the data object and function info sections: + each of these is an array of strtab indexes, mapped 1:1 to the corresponding + data object / function info section, giving each entry in those sections a + name so that the linker can correlate them with final symtab entries and + reorder them accordingly (dropping the indexes in the process). + Variable records (as distinct from data objects) provide a modicum of support for non-ELF systems, mapping a variable name to a CTF type ID. The variable - names are sorted into ASCIIbetical order, permitting binary searching. + names are sorted into ASCIIbetical order, permitting binary searching. We do + not define how the consumer maps these variable names to addresses or + anything else, or indeed what these names represent: they might be names + looked up at runtime via dlsym() or names extracted at runtime by a debugger + or anything else the consumer likes. The data types section is a list of variable size records that represent each type, in order by their ID. The types themselves form a directed graph, where each node may contain one or more outgoing edges to other type nodes, - denoted by their ID. + denoted by their ID. Most type nodes are standalone or point backwards to + earlier nodes, but this is not required: nodes can point to later nodes, + particularly structure and union members. Strings are recorded as a string table ID (0 or 1) and a byte offset into the string table. String table 0 is the internal CTF string table. String table @@ -125,9 +143,12 @@ typedef struct ctf_header ctf_preamble_t cth_preamble; uint32_t cth_parlabel; /* Ref to name of parent lbl uniq'd against. */ uint32_t cth_parname; /* Ref to basename of parent. */ + uint32_t cth_cuname; /* Ref to CU name (may be 0). */ uint32_t cth_lbloff; /* Offset of label section. */ uint32_t cth_objtoff; /* Offset of object section. */ uint32_t cth_funcoff; /* Offset of function section. */ + uint32_t cth_objtidxoff; /* Offset of object index section. */ + uint32_t cth_funcidxoff; /* Offset of function index section. */ uint32_t cth_varoff; /* Offset of variable section. */ uint32_t cth_typeoff; /* Offset of type section. */ uint32_t cth_stroff; /* Offset of string section. */ @@ -142,13 +163,14 @@ typedef struct ctf_header /* Data format version number. */ -/* v1 upgraded to v2 is not quite the same as native v2 (the boundary between - parent and child types is different), and you can write it out again via - ctf_compress_write(), so we must track whether the thing was originally v1 or - not. If we were writing the header from scratch, we would add a *pair* of - version number fields to allow for this, but this will do for now. (A flag - will not do, because we need to encode both the version we came from and the - version we went to, not just "we were upgraded".) */ +/* v1 upgraded to a later version is not quite the same as the native form, + because the boundary between parent and child types is different but not + recorded anywhere, and you can write it out again via ctf_compress_write(), + so we must track whether the thing was originally v1 or not. If we were + writing the header from scratch, we would add a *pair* of version number + fields to allow for this, but this will do for now. (A flag will not do, + because we need to encode both the version we came from and the version we + went to, not just "we were upgraded".) */ # define CTF_VERSION_1 1 # define CTF_VERSION_1_UPGRADED_3 2 @@ -265,6 +287,7 @@ union #define CTF_NAME_STID(name) ((name) >> 31) #define CTF_NAME_OFFSET(name) ((name) & CTF_MAX_NAME) +#define CTF_SET_STID(name, stid) ((name) | (stid) << 31) /* V2 only. */ #define CTF_TYPE_INFO(kind, isroot, vlen) \ @@ -378,13 +401,17 @@ union ctt_type, which must be a type which has an encoding (fp, int, or enum). We also store the referenced type in here, because it is easier to keep the ctt_size correct for the slice than to shuffle the size into here and keep - the ctt_type where it is for other types. */ + the ctt_type where it is for other types. + + In a future version, where we loosen requirements on alignment in the CTF + file, the cts_offset and cts_bits will be chars: but for now they must be + shorts or everything after a slice will become unaligned. */ typedef struct ctf_slice { uint32_t cts_type; - unsigned char cts_offset; - unsigned char cts_bits; + unsigned short cts_offset; + unsigned short cts_bits; } ctf_slice_t; typedef struct ctf_array From patchwork Mon Sep 9 04:28:20 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Indu Bhagat X-Patchwork-Id: 1159593 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-508565-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=oracle.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="Gc9W11di"; dkim=pass (2048-bit key; unprotected) header.d=oracle.com header.i=@oracle.com header.b="WRbAXZSj"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 46RZtZ52pRz9s4Y for ; Mon, 9 Sep 2019 14:29:10 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:subject:date:message-id:in-reply-to:references; q=dns; s= default; b=sQtY81pYWvUoCEFqW1pHbTZrrfGkIT4sIFX8H45AMkTu9Xf3mtJza F0NrIXbDCm4og9ZE68yRnULb3C/QNfKpJs1ZHf60k6aYQgBf04GD8AX7c1nwimvp 2dsauIlCC+ubzKRlEgU4Ta7Ocb+NLnKW50A/F2ZaslbIOmqBC/yBy8= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:subject:date:message-id:in-reply-to:references; s=default; bh=Gn/sJKK8kX1+tcGRIH8pCCsuWTI=; b=Gc9W11disKQDLuPjwUQAvVFPInw1 0qbD+n9TFJRmAbn8lSow63oNc/+sondLoGWSgaD+yJ2J1VH8yFwvgLQaX4Kz6RHF 245HfjUfxO0A9ZmBYXPibrxg10es/Pw0dhQL7Y0n+biL6th8E4Xs9NnArN9Q1Hqi A33G8w51ANPHckc= Received: (qmail 109380 invoked by alias); 9 Sep 2019 04:28:49 -0000 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 Received: (qmail 109342 invoked by uid 89); 9 Sep 2019 04:28:49 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-21.4 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, SPF_HELO_PASS, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 spammy=Two, Variable, vindictive, upper X-HELO: userp2130.oracle.com Received: from userp2130.oracle.com (HELO userp2130.oracle.com) (156.151.31.86) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 09 Sep 2019 04:28:42 +0000 Received: from pps.filterd (userp2130.oracle.com [127.0.0.1]) by userp2130.oracle.com (8.16.0.27/8.16.0.27) with SMTP id x894Niqt004418 for ; Mon, 9 Sep 2019 04:28:40 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oracle.com; h=from : to : subject : date : message-id : in-reply-to : references; s=corp-2019-08-05; bh=egHNwbSyELaiO1NG1T2/3NB0HdtxWR4oAHDJci0yroE=; b=WRbAXZSj2G8GpQ1Myt/9pjYhkyzd4FLPOlEQjVlxepAbFLsA3HiQpkrXU8F3W53ET2YW uLLByMQirfHJ/hriELtCo0HteawlZzoZo4YWI4BwV0Y7Iul6sUA5YXZHpCTowBQC/3d7 hKoRBYsfOgcJUNHRf8ky5dH0G3suDeUz52H2MmzcptmThFM/rF8DVfK3/6LGhewgrf2C hdhZ6L7d+UYF3XfxYww3CsdDKZbHeMtV0bCpswyQjqsqD0JMV2DMivC2E5htM3trLWNB MLP4z87JL/wdvbsUy+hHElZLP8btbZVkrdHknm3iljQ7KxniB/Qe5BD3NP3NsgANJMJ0 og== Received: from userp3020.oracle.com (userp3020.oracle.com [156.151.31.79]) by userp2130.oracle.com with ESMTP id 2uw1m8hhgn-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK) for ; Mon, 09 Sep 2019 04:28:40 +0000 Received: from pps.filterd (userp3020.oracle.com [127.0.0.1]) by userp3020.oracle.com (8.16.0.27/8.16.0.27) with SMTP id x894Sd5u005871 for ; Mon, 9 Sep 2019 04:28:39 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by userp3020.oracle.com with ESMTP id 2uv3wkywbs-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK) for ; Mon, 09 Sep 2019 04:28:38 +0000 Received: from abhmp0002.oracle.com (abhmp0002.oracle.com [141.146.116.8]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id x894SU9p031439 for ; Mon, 9 Sep 2019 04:28:32 GMT Received: from ibhagatpc.us.oracle.com (/10.65.144.100) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Sun, 08 Sep 2019 21:28:30 -0700 From: Indu Bhagat To: gcc-patches@gcc.gnu.org Subject: [PATCH,RFC,V5 5/6] Update CTF testsuite Date: Sun, 8 Sep 2019 21:28:20 -0700 Message-Id: <1568003301-11457-6-git-send-email-indu.bhagat@oracle.com> In-Reply-To: <1568003301-11457-1-git-send-email-indu.bhagat@oracle.com> References: <1568003301-11457-1-git-send-email-indu.bhagat@oracle.com> [Changes from V4] Added new testcases - gcc.dg/debug/ctf/ctf-bitfields-3.c - gcc.dg/debug/ctf/ctf-bitfields-4.c - gcc.dg/debug/ctf/ctf-cvr-quals-4.c - gcc.dg/debug/ctf/ctf-forward-3.c - gcc.dg/debug/ctf/ctf-function-pointers-2.c gcc/testsuite/ChangeLog: * gcc.dg/debug/ctf/ctf-2.c: New test. * gcc.dg/debug/ctf/ctf-anonymous-struct-1.c: New test. * gcc.dg/debug/ctf/ctf-anonymous-union-1.c: New test. * gcc.dg/debug/ctf/ctf-array-1.c: New test. * gcc.dg/debug/ctf/ctf-array-2.c: New test. * gcc.dg/debug/ctf/ctf-bitfields-1.c: New test. * gcc.dg/debug/ctf/ctf-bitfields-2.c: New test. * gcc.dg/debug/ctf/ctf-bitfields-3.c: New test. * gcc.dg/debug/ctf/ctf-bitfields-4.c: New test. * gcc.dg/debug/ctf/ctf-complex-1.c: New test. * gcc.dg/debug/ctf/ctf-cvr-quals-1.c: New test. * gcc.dg/debug/ctf/ctf-cvr-quals-2.c: New test. * gcc.dg/debug/ctf/ctf-cvr-quals-3.c: New test. * gcc.dg/debug/ctf/ctf-cvr-quals-4.c: New test. * gcc.dg/debug/ctf/ctf-enum-1.c: New test. * gcc.dg/debug/ctf/ctf-enum-2.c: New test. * gcc.dg/debug/ctf/ctf-float-1.c: New test. * gcc.dg/debug/ctf/ctf-forward-1.c: New test. * gcc.dg/debug/ctf/ctf-forward-2.c: New test. * gcc.dg/debug/ctf/ctf-forward-3.c: New test. * gcc.dg/debug/ctf/ctf-func-index-1.c: New test. * gcc.dg/debug/ctf/ctf-function-pointers-1.c: New test. * gcc.dg/debug/ctf/ctf-function-pointers-2.c: New test. * gcc.dg/debug/ctf/ctf-functions-1.c: New test. * gcc.dg/debug/ctf/ctf-int-1.c: New test. * gcc.dg/debug/ctf/ctf-objt-index-1.c: New test. * gcc.dg/debug/ctf/ctf-pointers-1.c: New test. * gcc.dg/debug/ctf/ctf-skip-types-1.c: New test. * gcc.dg/debug/ctf/ctf-str-table-1.c: New test. * gcc.dg/debug/ctf/ctf-struct-1.c: New test. * gcc.dg/debug/ctf/ctf-struct-2.c: New test. * gcc.dg/debug/ctf/ctf-struct-array-1.c: New test. * gcc.dg/debug/ctf/ctf-typedef-1.c: New test. * gcc.dg/debug/ctf/ctf-typedef-struct-1.c: New test. * gcc.dg/debug/ctf/ctf-union-1.c: New test. * gcc.dg/debug/ctf/ctf-variables-1.c: New test. --- gcc/testsuite/ChangeLog | 39 +++++++++++++++++++ gcc/testsuite/gcc.dg/debug/ctf/ctf-2.c | 10 +++++ .../gcc.dg/debug/ctf/ctf-anonymous-struct-1.c | 23 +++++++++++ .../gcc.dg/debug/ctf/ctf-anonymous-union-1.c | 26 +++++++++++++ gcc/testsuite/gcc.dg/debug/ctf/ctf-array-1.c | 31 +++++++++++++++ gcc/testsuite/gcc.dg/debug/ctf/ctf-array-2.c | 39 +++++++++++++++++++ gcc/testsuite/gcc.dg/debug/ctf/ctf-bitfields-1.c | 30 +++++++++++++++ gcc/testsuite/gcc.dg/debug/ctf/ctf-bitfields-2.c | 39 +++++++++++++++++++ gcc/testsuite/gcc.dg/debug/ctf/ctf-bitfields-3.c | 16 ++++++++ gcc/testsuite/gcc.dg/debug/ctf/ctf-bitfields-4.c | 22 +++++++++++ gcc/testsuite/gcc.dg/debug/ctf/ctf-complex-1.c | 22 +++++++++++ gcc/testsuite/gcc.dg/debug/ctf/ctf-cvr-quals-1.c | 44 ++++++++++++++++++++++ gcc/testsuite/gcc.dg/debug/ctf/ctf-cvr-quals-2.c | 30 +++++++++++++++ gcc/testsuite/gcc.dg/debug/ctf/ctf-cvr-quals-3.c | 41 ++++++++++++++++++++ gcc/testsuite/gcc.dg/debug/ctf/ctf-cvr-quals-4.c | 21 +++++++++++ gcc/testsuite/gcc.dg/debug/ctf/ctf-enum-1.c | 21 +++++++++++ gcc/testsuite/gcc.dg/debug/ctf/ctf-enum-2.c | 26 +++++++++++++ gcc/testsuite/gcc.dg/debug/ctf/ctf-float-1.c | 16 ++++++++ gcc/testsuite/gcc.dg/debug/ctf/ctf-forward-1.c | 36 ++++++++++++++++++ gcc/testsuite/gcc.dg/debug/ctf/ctf-forward-2.c | 16 ++++++++ gcc/testsuite/gcc.dg/debug/ctf/ctf-forward-3.c | 21 +++++++++++ gcc/testsuite/gcc.dg/debug/ctf/ctf-func-index-1.c | 25 ++++++++++++ .../gcc.dg/debug/ctf/ctf-function-pointers-1.c | 24 ++++++++++++ .../gcc.dg/debug/ctf/ctf-function-pointers-2.c | 18 +++++++++ gcc/testsuite/gcc.dg/debug/ctf/ctf-functions-1.c | 34 +++++++++++++++++ gcc/testsuite/gcc.dg/debug/ctf/ctf-int-1.c | 17 +++++++++ gcc/testsuite/gcc.dg/debug/ctf/ctf-objt-index-1.c | 29 ++++++++++++++ gcc/testsuite/gcc.dg/debug/ctf/ctf-pointers-1.c | 26 +++++++++++++ gcc/testsuite/gcc.dg/debug/ctf/ctf-skip-types-1.c | 33 ++++++++++++++++ gcc/testsuite/gcc.dg/debug/ctf/ctf-str-table-1.c | 26 +++++++++++++ gcc/testsuite/gcc.dg/debug/ctf/ctf-struct-1.c | 25 ++++++++++++ gcc/testsuite/gcc.dg/debug/ctf/ctf-struct-2.c | 30 +++++++++++++++ .../gcc.dg/debug/ctf/ctf-struct-array-1.c | 36 ++++++++++++++++++ gcc/testsuite/gcc.dg/debug/ctf/ctf-typedef-1.c | 23 +++++++++++ .../gcc.dg/debug/ctf/ctf-typedef-struct-1.c | 12 ++++++ gcc/testsuite/gcc.dg/debug/ctf/ctf-union-1.c | 14 +++++++ gcc/testsuite/gcc.dg/debug/ctf/ctf-variables-1.c | 25 ++++++++++++ 37 files changed, 966 insertions(+) create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-2.c create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-anonymous-struct-1.c create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-anonymous-union-1.c create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-array-1.c create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-array-2.c create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-bitfields-1.c create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-bitfields-2.c create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-bitfields-3.c create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-bitfields-4.c create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-complex-1.c create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-cvr-quals-1.c create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-cvr-quals-2.c create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-cvr-quals-3.c create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-cvr-quals-4.c create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-enum-1.c create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-enum-2.c create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-float-1.c create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-forward-1.c create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-forward-2.c create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-forward-3.c create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-func-index-1.c create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-function-pointers-1.c create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-function-pointers-2.c create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-functions-1.c create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-int-1.c create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-objt-index-1.c create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-pointers-1.c create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-skip-types-1.c create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-str-table-1.c create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-struct-1.c create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-struct-2.c create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-struct-array-1.c create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-typedef-1.c create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-typedef-struct-1.c create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-union-1.c create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-variables-1.c diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-2.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-2.c new file mode 100644 index 0000000..891f20e --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-2.c @@ -0,0 +1,10 @@ +/* A LEVEL of 0 with -gt turns off CTF debug info generation. */ + +/* { dg-do compile } */ +/* { dg-options "-gt0 -dA" } */ + +/* { dg-final { scan-assembler-times "0xdff2.*CTF preamble magic number" 0} } */ +/* { dg-final { scan-assembler-times "0x4.*CTF preamble version" 0 } } */ +/* { dg-final { scan-assembler-times "0.*CTF preamble flags" 0 } } */ + +const char * _CONTEXT_NAME = "foobar"; diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-anonymous-struct-1.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-anonymous-struct-1.c new file mode 100644 index 0000000..0973b2b --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-anonymous-struct-1.c @@ -0,0 +1,23 @@ +/* Test compilation and CTF generation of anonymous structs. An anonymous + struct type is encoded as no-name CTF struct type. + + For this testcase, a single CTF anonymous struct is expected. + struct {} : ctt_name = 0 (point to offset 0 in the CTF string table to + denote empty string) + + Two CTF struct records should be generated in total. + struct a : ctt_info = 0x1a000002 (2 fields) + struct {} : ctt_info = 0x1a000001 (1 field) */ + +/* { dg-do compile ) */ +/* { dg-options "-O0 -gt -dA" } */ + +/* { dg-final { scan-assembler-times "\[\t \]0\[\t \]+\[^\n\]*ctt_name" 1 } } */ +/* { dg-final { scan-assembler-times "0x1a000002\[\t \]+\[^\n\]*ctt_info" 1 } } */ +/* { dg-final { scan-assembler-times "0x1a000001\[\t \]+\[^\n\]*ctt_info" 1 } } */ + +struct a +{ + struct { int b1; } a1; + int a2; +} my_a; diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-anonymous-union-1.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-anonymous-union-1.c new file mode 100644 index 0000000..71b491a --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-anonymous-union-1.c @@ -0,0 +1,26 @@ +/* Test compilation and CTF generation of anonymous union. An anonymous union + is encoded as no-name CTF union type. + + For this testcase, a single CTF anonymous union is expected. + struct {} : ctt_name = 0 (point to offset 0 in the CTF string table to + denote empty string) + + Two CTF struct records should be generated in total. + struct anon_union : ctt_info = 0x1a000001 (1 field) + union {} : ctt_info = 0x1e000002 (2 fields) */ + +/* { dg-do compile ) */ +/* { dg-options "-O0 -gt -dA" } */ + +/* { dg-final { scan-assembler-times "\[\t \]0\[\t \]+\[^\n\]*ctt_name" 1 } } */ +/* { dg-final { scan-assembler-times "0x1a000001\[\t \]+\[^\n\]*ctt_info" 1 } } */ +/* { dg-final { scan-assembler-times "0x1e000002\[\t \]+\[^\n\]*ctt_info" 1 } } */ + +struct anon_union +{ + union + { + char name; + int value; + }; +} my_anon_u; diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-array-1.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-array-1.c new file mode 100644 index 0000000..cca8c42 --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-array-1.c @@ -0,0 +1,31 @@ +/* CTF generation for array type. + + Unsized arrays are encoded with a 0 for the number of elements. + + In this testcase, 5 distinct CTF records for arrays are expected + b1 : cta_nelems = 2 + c1 : cta_nelems = 3 + a1 : cta_nelems = 2, 5 + buf1 : cta_nelems = 0. */ + +/* { dg-do compile ) */ +/* { dg-options "-O0 -gt -dA" } */ + +/* { dg-final { scan-assembler-times "0x12000000\[\t \]+\[^\n\]*ctt_info" 5 } } */ + +/* { dg-final { scan-assembler-times "\[\t \]0x2\[\t \]+\[^\n\]*cta_nelems" 2 } } */ +/* { dg-final { scan-assembler-times "\[\t \]0x3\[\t \]+\[^\n\]*cta_nelems" 1 } } */ +/* { dg-final { scan-assembler-times "\[\t \]0x5\[\t \]+\[^\n\]*cta_nelems" 1 } } */ +/* { dg-final { scan-assembler-times "\[\t \]0\[\t \]+\[^\n\]*cta_nelems" 1 } } */ + +int b1[2] = {0,1}; +int c1[5] = {0,1,2,3,4}; +int a1[2][3] = { {3,4,5}, {2,3,4} }; + +/* Variable length struct using arrays. */ +struct my_array +{ + int flags; + int length; + int buf[]; +} my_array_obj; diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-array-2.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-array-2.c new file mode 100644 index 0000000..744f15e --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-array-2.c @@ -0,0 +1,39 @@ +/* CTF generation for unsized arrays. + + Unsized arrays are encoded with a 0 for the number of elements. The type + of array index is the INT type. + + TBD_CTF_FORMAT_OPEN_ISSUES (1) - + This testcase makes a note of the case of a probable misrepresentation. + See Note 1 and Note 2 below. + + In the CTF section, these types are encoded as : + + Variables: + _CTF_NEWSTR -> 7: const char [0] (size 0x0) + _CTF_SECTION -> 6: const char [5] (size 0x5) + b1 -> 2: int [0] (size 0x0) + b2 -> 3: int [0] (size 0x0) + + Note 1 : There is misrepresentation in that b1 and b2 are specified + differently by the user. + Note 2 : It is arguable though whether the representation for + _CTF_NEWSTR is incorrect. */ + +/* { dg-do compile ) */ +/* { dg-options "-O0 -gt -dA" } */ + +/* { dg-final { scan-assembler-times "0x12000000\[\t \]+\[^\n\]*ctt_info" 4 } } */ + +/* { dg-final { scan-assembler-times "\[\t \]0x1\[\t \]+\[^\n\]*cta_index" 4 } } */ +/* { dg-final { scan-assembler-times "\[\t \]0\[\t \]+\[^\n\]*cta_nelems" 3 } } */ +/* { dg-final { scan-assembler-times "\[\t \]0x5\[\t \]+\[^\n\]*cta_nelems" 1 } } */ + +static int b1[] = {}; + +int b2[0]; + +const char _CTF_SECTION[] = ".ctf"; + +extern const char _CTF_NEWSTR[]; +const char _CTF_NEWSTR[] = "ctfinfo"; diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-bitfields-1.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-bitfields-1.c new file mode 100644 index 0000000..5f26629 --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-bitfields-1.c @@ -0,0 +1,30 @@ +/* CTF generation for bitfields. + + In this testcase, two slices are expected - one for enum and the other for + int. CTF slices are unnamed records. */ + +/* { dg-do compile ) */ +/* { dg-options "-O0 -gt -dA" } */ + +/* { dg-final { scan-assembler-times "\[\t \]0x2\[\t \]+\[^\n\]*cts_bits" 1 } } */ +/* { dg-final { scan-assembler-times "\[\t \]0x3\[\t \]+\[^\n\]*cts_bits" 1 } } */ +/* { dg-final { scan-assembler-times "\[\t \]0\[\t \]+\[^\n\]*ctt_name" 2 } } */ + +enum color +{ + RED, + GREEN, + BLUE, + YELLOW, + ORANGE, + BLACK +}; + +struct quickcolor +{ + enum color col:3; + int brushid:2; + int strokes; +}; + +struct quickcolor qc; diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-bitfields-2.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-bitfields-2.c new file mode 100644 index 0000000..ed85cf3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-bitfields-2.c @@ -0,0 +1,39 @@ +/* The bitfield type (int) may be shared, but slices are not de-duplicated. + + In this testcase, it is expected to see a total of 6 CTF slices and 2 CTF + integer types for the bitfields - unsigned long long and signed long long. + + cts_offset is the offset of the bitfield into a machine word. + TBD - hardcoding cts_offset checks into the testcase will cause it to break + across targets with different BIT_PER_WORD. Is there a way to add + cts_offset related checks in the testcase? */ + +/* { dg-do compile ) */ +/* { dg-options "-O0 -gt -dA" } */ + +/* { dg-final { scan-assembler-times "\[\t \]0x6\[\t \]+\[^\n\]*cts_type" 3 } } */ +/* { dg-final { scan-assembler-times "\[\t \]0x2\[\t \]+\[^\n\]*cts_type" 3 } } */ + +/* { dg-final { scan-assembler-times "\[\t \]0xf\[\t \]+\[^\n\]*cts_bits" 2 } } */ +/* { dg-final { scan-assembler-times "\[\t \]0x21\[\t \]+\[^\n\]*cts_bits" 2 } } */ +/* { dg-final { scan-assembler-times "\[\t \]0x10\[\t \]+\[^\n\]*cts_bits" 2 } } */ + +/* { dg-final { scan-assembler-times "ascii \"long long unsigned int.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */ +/* { dg-final { scan-assembler-times "ascii \"long long int.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */ + +struct fields +{ + unsigned long long u1 : 15; + unsigned long long u2 : 33; + unsigned long long u3 : 16; + signed long long s1 : 15; + signed long long s2 : 33; + signed long long s3 : 16; +} flags; + +int i = 33; + +int main () +{ + return flags.u1 + i; +} diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-bitfields-3.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-bitfields-3.c new file mode 100644 index 0000000..dcb6a2a --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-bitfields-3.c @@ -0,0 +1,16 @@ +/* The bool bitfield type. */ + +/* { dg-do compile ) */ +/* { dg-options "-O0 -gt -dA" } */ + +/* { dg-final { scan-assembler-times "\[\t \]0x2\[\t \]+\[^\n\]*cts_type" 2 } } */ +/* { dg-final { scan-assembler-times "\[\t \]0x1\[\t \]+\[^\n\]*cts_bits" 2 } } */ + +/* { dg-final { scan-assembler-times "ascii \"_Bool.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */ + +#include + +struct open_file { + bool mmapped:1; + bool released:1; +} of; diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-bitfields-4.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-bitfields-4.c new file mode 100644 index 0000000..4fa4764 --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-bitfields-4.c @@ -0,0 +1,22 @@ +/* The zero sized bitfield. + + In this testcase, three slices are expected - two of which correspond to + type int, and one corresponds to unsigned int. */ + +/* { dg-do compile ) */ +/* { dg-options "-O0 -gt -dA" } */ + +/* { dg-final { scan-assembler-times "\[\t \]0x2\[\t \]+\[^\n\]*cts_type" 2 } } */ +/* { dg-final { scan-assembler-times "\[\t \]0x4\[\t \]+\[^\n\]*cts_type" 1 } } */ + +/* { dg-final { scan-assembler-times "\[\t \]0x5\[\t \]+\[^\n\]*cts_bits" 1 } } */ +/* { dg-final { scan-assembler-times "\[\t \]0xa\[\t \]+\[^\n\]*cts_bits" 1 } } */ +/* { dg-final { scan-assembler-times "\[\t \]0\[\t \]+\[^\n\]*cts_bits" 1 } } */ + +/* { dg-final { scan-assembler-times "ctm_name" 3 } } */ +struct foo +{ + int a:5; + unsigned:0; + int b:10; +} foome; diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-complex-1.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-complex-1.c new file mode 100644 index 0000000..3d02b87 --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-complex-1.c @@ -0,0 +1,22 @@ +/* Tests for CTF complex base types. + + CTF does not have representation for COMPLEX integer types. + + This testcase has a mix of C constructs containing COMPLEX_TYPE. */ + +/* { dg-do compile ) */ +/* { dg-options "-O0 -gt -dA" } */ + +/* { dg-final { scan-assembler-times "\[\t \]0xa000000\[\t \]+\[^\n\]*ctt_info" 3 } } */ + +/* { dg-final { scan-assembler-times "ascii \"complex double.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */ +/* { dg-final { scan-assembler-times "ascii \"complex long double.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */ +/* { dg-final { scan-assembler-times "ascii \"complex float.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */ + +#include + +double complex z1 = I * I; + +const long double complex z2 = I * I; + +float complex z4 = 1+2.11*I; diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-cvr-quals-1.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-cvr-quals-1.c new file mode 100644 index 0000000..318a171 --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-cvr-quals-1.c @@ -0,0 +1,44 @@ +/* Test compilation of stubs with various qualifiers - const, restrict and + volatile. + + Testcase includes a std header to allow testing of shared types across + files. Only one CTF record for int is expected. + + CTF records for CVR qualifiers are no-name records. In this testcase, there + are 7 qualifiers across constructs. 2 more no-name CTF records correspond to + CTF pointer records. + + TYPEID: name string (size) -> ref TYPEID : ref name string (size) -> ... + + b: volatile int (size 4) -> 5: int (size 4) + c: const volatile int (size 4) -> b: volatile int (size 4) -> 5: int (size 4) + e: int *restrict (size 8) -> d: int * (size 8) -> 5: int (size 4) + f: const int (size 4) -> 5: int (size 4) + 10: const int * (size 8) -> f: const int (size 4) -> 5: int (size 4) + 12: int *const (size 8) -> d: int * (size 8) -> 5: int (size 4) + 14: const int *restrict (size 8) -> 10: const int * (size 8) -> f: const int (size 4) -> 5: int (size 4) + */ + +/* { dg-do compile ) */ +/* { dg-options "-O0 -gt -dA" } */ + +/* { dg-final { scan-assembler-times "ascii \"int.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */ +/* { dg-final { scan-assembler-times "\[\t \]0\[\t \]+\[^\n\]*ctt_name" 9 } } */ +/* { dg-final { scan-assembler-times "\[\t \]0xe000000\[\t \]+\[^\n\]*ctt_info" 2 } } */ + +#include "stddef.h" + +const volatile int a = 5; +int *restrict b; + +const int * i; +int const * j; + +typedef int * INTP; +const INTP int_p; + +void foo (size_t n, int *restrict p, const int *restrict q) +{ + while (n-- > 0) + *p++ = *q++; +} diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-cvr-quals-2.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-cvr-quals-2.c new file mode 100644 index 0000000..8ce6676 --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-cvr-quals-2.c @@ -0,0 +1,30 @@ +/* Test compilation of stubs with various expressions involving const + qualifier. + + In this testcase, a single CTF record for const int is expected. A total of + two const qualifier CTF records are expected (const int and const struct + s1). */ + +/* { dg-do compile ) */ +/* { dg-options "-O0 -gt -dA" } */ + +/* { dg-final { scan-assembler-times "ascii \"int.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */ +/* { dg-final { scan-assembler-times "\[\t \]0x32000000\[\t \]+\[^\n\]*ctt_info" 2 } } */ + +struct mystruct +{ + struct + { + int a; + const int b; + } s1; + char * name; +} my_a; + +struct s1 +{ + int i; + const int ci; +} s; + +const struct s1 cs; diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-cvr-quals-3.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-cvr-quals-3.c new file mode 100644 index 0000000..6ec17a6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-cvr-quals-3.c @@ -0,0 +1,41 @@ +/* Test compilation of stubs with various expressions involving const and + volatile qualifiers. + + In this testcase, it is expected to have const and volatile CTF records, + some of which are shared or referenced (shown by '->' below) : + + Types: + 1: unsigned char (size 1) + 2: volatile unsigned char (size 1) -> 1: unsigned char (size 1) + 3: const volatile unsigned char (size 1) -> 2: volatile unsigned char (size 1) -> 1: unsigned char (size 1) + 4: const volatile unsigned char * (size 8) -> 3: const volatile unsigned char (size 1) -> 2: volatile unsigned char (size 1) -> 1: unsigned char (size 1) [POINTER_TYPE] + 5: int (size 4) + 6: float (size 4) + 7: volatile float (size 4) -> 6: float (size 4) + 8: volatile float [2] (size 8) [ARRAY_TYPE] + 9: char (size 1) + a: volatile char (size 1) -> 9: char (size 1) + b: const volatile char (size 1) -> a: volatile char (size 1) -> 9: char (size 1) + c: const volatile char [2] (size 2) [ARRAY_TYPE] + + Types 2, 3, 7, a, and b are CTF types of kind CTF_K_CONST or CTF_K_VOLATILE. */ + +/* { dg-do compile ) */ +/* { dg-options "-O0 -gt -dA" } */ + +/* { dg-final { scan-assembler-times "ascii \"int.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */ +/* { dg-final { scan-assembler-times "\[\t \]0x2e000000\[\t \]+\[^\n\]*ctt_info" 3 } } */ +/* { dg-final { scan-assembler-times "\[\t \]0x32000000\[\t \]+\[^\n\]*ctt_info" 2 } } */ +/* Two arrays. */ +/* { dg-final { scan-assembler-times "\[\t \]0x12000000\[\t \]+\[^\n\]*ctt_info" 2 } } */ + + +const volatile unsigned char vicar = 11; + +const volatile unsigned char * vicarage = &vicar; + +volatile float vilify[2]; + +const volatile char victor = 'Y'; + +const volatile char vindictive[2]; diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-cvr-quals-4.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-cvr-quals-4.c new file mode 100644 index 0000000..f1aeedc --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-cvr-quals-4.c @@ -0,0 +1,21 @@ +/* Test compilation of stubs with various qualifiers - const, restrict and + volatile. + + CTF records for CVR qualifiers are no-name records. In this testcase, there + is 1 const qualifier. 1 more no-name CTF record corresponds to the CTF + pointer record. */ + +/* { dg-do compile ) */ +/* { dg-options "-O0 -gt -dA" } */ + +/* { dg-final { scan-assembler-times "\[\t \]0\[\t \]+\[^\n\]*ctt_name" 2 } } */ +/* { dg-final { scan-assembler-times "\[\t \]0xe000000\[\t \]+\[^\n\]*ctt_info" 1 } } */ +/* { dg-final { scan-assembler-times "\[\t \]0x32000000\[\t \]+\[^\n\]*ctt_info" 1 } } */ + +typedef const struct howto_struct howto_type; + +typedef struct entry +{ + int addend; + howto_type *howto; +} how_ent; diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-enum-1.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-enum-1.c new file mode 100644 index 0000000..d91a419 --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-enum-1.c @@ -0,0 +1,21 @@ +/* CTF generation for enums. */ + +/* { dg-do compile ) */ +/* { dg-options "-O0 -gt -dA" } */ + +/* { dg-final { scan-assembler-times "ascii \"RED.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */ +/* { dg-final { scan-assembler-times "ascii \"GREEN.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */ +/* { dg-final { scan-assembler-times "ascii \"BLUE.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */ +/* { dg-final { scan-assembler-times "ascii \"YELLOW.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */ +/* { dg-final { scan-assembler-times "cte_value" 4} } */ + + +enum foo_color +{ + RED, + GREEN, + BLUE, + YELLOW +}; + +enum foo_color my_color; diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-enum-2.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-enum-2.c new file mode 100644 index 0000000..ef87691 --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-enum-2.c @@ -0,0 +1,26 @@ +/* CTF generation for enums. + + CTF represents enum values with an int32_t. The compiler skips adding these + enum values into the CTF for the enum type. This will be fixed soon in the + format. TBD_CTF_REPRESENTATION_LIMIT. + + In this testcase, CTF for enumerator GFS_MONOTONIC will not be generated. */ + +/* { dg-do compile ) */ +/* { dg-options "-O0 -gt -dA" } */ + +/* { dg-final { scan-assembler-times "ascii \"GFS_MONOTONIC.0\"\[\t \]+\[^\n\]*ctf_string" 0 } } */ +/* { dg-final { scan-assembler-times "ascii \"GFS_RUNTIME.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */ +/* { dg-final { scan-assembler-times "ascii \"GFS_STATIC.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */ +/* { dg-final { scan-assembler-times "cte_value" 2} } */ + + +enum gomp_schedule_type +{ + GFS_RUNTIME, + GFS_STATIC, + GFS_MONOTONIC = 0x80000000U +}; + +enum gomp_schedule_type gsch_type; + diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-float-1.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-float-1.c new file mode 100644 index 0000000..ae2dfc2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-float-1.c @@ -0,0 +1,16 @@ +/* Tests for CTF float base types. + - Verify that there is a single record for the base types. */ + +/* { dg-do compile ) */ +/* { dg-options "-O0 -gt -dA" } */ +/* { dg-final { scan-assembler-times "ascii \"float.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */ +/* { dg-final { scan-assembler-times "ascii \"double.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */ +/* { dg-final { scan-assembler-times "ascii \"long double.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */ + +float a; +float b = 33; + +double c = 44; +double d = 45; + +long double e; diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-forward-1.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-forward-1.c new file mode 100644 index 0000000..8254d3e --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-forward-1.c @@ -0,0 +1,36 @@ +/* CTF forward type is generated for forward declarations of types in C. + + Check that the ctf-kind of CTF_K_FOWARD type is CTF_K_STRUCT or CTF_K_UNION. + For forward types, the compiler encodes the CTF kind in the ctt_type field. + CTF_K_FORWARD is used as the CTF type as usual in the ctt_info. */ + +/* Note - A value of 6 in "ctt_size or ctt_type" appears twice in this + testcase. This might be misconstrued as 2 CTK_K_FORWARD records of struct + type. The second assembler tag is due to a ref type in a CVR CTF record. + TBD - perhaps a more robust string pattern is needed. */ + +/* { dg-do compile ) */ +/* { dg-options "-O0 -gt -dA" } */ + +/* { dg-final { scan-assembler-times "\[\t \]0x26000000\[\t \]+\[^\n\]*ctt_info" 2 } } */ +/* { dg-final { scan-assembler-times "\[\t \]0x6\[\t \]+\[^\n\]*ctt_size or ctt_type" 2 } } */ +/* { dg-final { scan-assembler-times "\[\t \]0x7\[\t \]+\[^\n\]*ctt_size or ctt_type" 1 } } */ + +typedef struct __locale_struct +{ + struct __locale_data *__locales[13]; /* forward struct type. */ + + const int *__ctype_toupper; + const char *__names[13]; +} *__locale_t; + +typedef __locale_t locale_t; + +typedef struct __inter_struct +{ + union __inter_data * __inters[13]; /* forward union type. */ + + const int * __ctype_kind; +} * __inter_t; + +typedef __inter_t inter_t; diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-forward-2.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-forward-2.c new file mode 100644 index 0000000..33080f2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-forward-2.c @@ -0,0 +1,16 @@ +/* CTF forward type is generated for forward declarations of enum types in C. + + Check that the ctf-kind of CTF_K_FOWARD type is CTF_K_ENUM. + For forward types, the compiler encodes the CTF kind in the ctt_type field. + CTF_K_FORWARD is used as the CTF type as usual in the ctt_info. */ + +/* { dg-do compile ) */ +/* { dg-options "-O0 -gt -dA" } */ + +/* { dg-final { scan-assembler-times "\[\t \]0x26000000\[\t \]+\[^\n\]*ctt_info" 1 } } */ +/* { dg-final { scan-assembler-times "\[\t \]0x8\[\t \]+\[^\n\]*ctt_size or ctt_type" 1 } } */ +/* { dg-final { scan-assembler-times "ascii \"vibgyor.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */ + +enum vibgyor; + +char * (*get_color_name) (enum vibgyor); diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-forward-3.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-forward-3.c new file mode 100644 index 0000000..cdb740b --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-forward-3.c @@ -0,0 +1,21 @@ +/* A compilation unit may have a forward declation of a type and the definition + of the type at a later point. + + CTF forward type is generated for forward declarations of types in C. + + Once the type is defined, the CTF generated for the forward declaration is + updated to non-root type. + + In this testcase, one CTF_K_FORWARD type and two CTF_K_STRUCT types are + expected. */ + +/* { dg-do compile ) */ +/* { dg-options "-O0 -gt -dA" } */ + +/* { dg-final { scan-assembler-times "\[\t \]0x24000000\[\t \]+\[^\n\]*ctt_info" 1 } } */ +/* { dg-final { scan-assembler-times "\[\t \]0x6\[\t \]+\[^\n\]*ctt_size or ctt_type" 1 } } */ +/* { dg-final { scan-assembler-times "\[\t \]0x8\[\t \]+\[^\n\]*ctt_size or ctt_type" 2 } } */ +/* { dg-final { scan-assembler-times "ascii \"afoo.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */ +/* { dg-final { scan-assembler-times "ascii \"bfoo.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */ +struct bar { struct foo * a; } barbar; +struct foo { int afoo; int bfoo; } foofoo; diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-func-index-1.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-func-index-1.c new file mode 100644 index 0000000..4215615 --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-func-index-1.c @@ -0,0 +1,25 @@ +/* CTF function index sub-section. + + A function index sub-section in the CTF section contains the offset to the + string name of the global function symbols. The number of entries in the + func info section and the func index section are always the same. + + In this testcase, 2 records in the function index section are expected. */ + +/* { dg-do compile ) */ +/* { dg-options "-O0 -gt -dA" } */ + +/* { dg-final { scan-assembler-times "funcinfo_name" 2 } } */ +/* { dg-final { scan-assembler-times "funcinfo_func_type" 2 } } */ +/* { dg-final { scan-assembler-times "ascii \"bar.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */ +/* { dg-final { scan-assembler-times "ascii \"foo.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */ + +int foo (void) +{ + return 0; +} + +int bar (int a) +{ + return 33 + a; +} diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-function-pointers-1.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-function-pointers-1.c new file mode 100644 index 0000000..e324445 --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-function-pointers-1.c @@ -0,0 +1,24 @@ +/* CTF generation of function pointers. */ + +/* { dg-do compile ) */ +/* { dg-options "-O0 -gt -dA" } */ +/* { dg-final { scan-assembler-times "\[\t \]0x16000001\[\t \]+\[^\n\]*ctt_info" 1 } } */ +/* { dg-final { scan-assembler-times "\[\t \]0x16000002\[\t \]+\[^\n\]*ctt_info" 1 } } */ +/* { dg-final { scan-assembler-times "\[\t \]0x16000003\[\t \]+\[^\n\]*ctt_info" 1 } } */ +/* { dg-final { scan-assembler-times "ascii \"__foo_fn.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */ +/* { dg-final { scan-assembler-times "ascii \"destroy.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */ +/* { dg-final { scan-assembler-times "ascii \"func.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */ + +int (*func) (int *, char); + +typedef int __foo_fn (void *__cookie, char *__buf, int __nbytes); + +typedef struct object +{ + int myint; + char mychar; + void (*destroy)(struct object *); +} object_t; + +object_t myobj; +__foo_fn fooit; diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-function-pointers-2.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-function-pointers-2.c new file mode 100644 index 0000000..4a88af4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-function-pointers-2.c @@ -0,0 +1,18 @@ +/* CTF generation of function pointers. + + In this testcase, there is a single function type expected for two + different function pointer types. */ + +/* { dg-do compile ) */ +/* { dg-options "-O0 -gt -dA" } */ +/* { dg-final { scan-assembler-times "\[\t \]0x16000001\[\t \]+\[^\n\]*ctt_info" 1 } } */ +/* { dg-final { scan-assembler-times "ascii \"rcu_callback_t.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */ +/* { dg-final { scan-assembler-times "ascii \"func.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */ + +struct callback_head { + struct callback_head *next; + void (*func) (struct callback_head *head); +} __attribute__ (( aligned (sizeof (void *)))); +#define rcu_head callback_head + +typedef void (*rcu_callback_t) (struct rcu_head *head); diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-functions-1.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-functions-1.c new file mode 100644 index 0000000..20bade1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-functions-1.c @@ -0,0 +1,34 @@ +/* CTF generation for functions with varargs or otherwise. + + In this testcase, it is expected to see one CTF_K_FUNCTION record with two + function arguments. The second function argument with a value of 0 + corresponds to the ellipsis. + + Example CTF section excerpt on x86_64 : + + .long 0x5 # ctt_name (name = format) + .long 0x16000002 # ctt_info (CTF_K_FUNCTION with 2 arguments) + .long 0x2 # ctt_size or ctt_type (return typeID) + .long 0x2 # dtu_argv (TypeID of the First argument) + .long 0 # dtu_argv (TypeID of the second argument) + .ascii "\0" # ctf_string + .ascii "int\0" # ctf_string + .ascii "format\0" # ctf_string + + */ + +/* { dg-do compile ) */ +/* { dg-options "-O0 -gt -dA" } */ + +/* { dg-final { scan-assembler-times "\[\t \]0x16000002\[\t \]+\[^\n\]*ctt_info" 1 } } */ +/* { dg-final { scan-assembler-times "dtu_argv" 2 } } */ +/* { dg-final { scan-assembler-times "\[\t \]0\[\t \]+\[^\n\]*dtu_argv" 1 } } */ + +int foo (void); + +int bar (int); + +int * format (int * fmt, ...) +{ + return fmt; +} diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-int-1.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-int-1.c new file mode 100644 index 0000000..88f2a3a --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-int-1.c @@ -0,0 +1,17 @@ +/* Tests for CTF integer base types. + - Verify that there is a single record for the base types. */ + +/* { dg-do compile ) */ +/* { dg-options "-O0 -gt -dA" } */ +/* { dg-final { scan-assembler-times "ascii \"int.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */ +/* { dg-final { scan-assembler-times "ascii \"short int.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */ +/* { dg-final { scan-assembler-times "ascii \"long int.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */ + +int a; +int b = 33; + +short int c = 44; +short int d = 45; + +long int e = 90; +long int f; diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-objt-index-1.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-objt-index-1.c new file mode 100644 index 0000000..8d380d8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-objt-index-1.c @@ -0,0 +1,29 @@ +/* CTF objext index sub-section. + + An object index sub-section in the CTF section contains the offset to the + string name of the global object symbols. The number of entries in the + obj info section and objt index section are always the same. + + In this testcase, 3 records in the object index section are expected. */ + +/* { dg-do compile ) */ +/* { dg-options "-O0 -gt -dA" } */ + +/* { dg-final { scan-assembler-times "objtinfo_name" 3 } } */ +/* { dg-final { scan-assembler-times "objtinfo_var_type" 3 } } */ +/* { dg-final { scan-assembler-times "ascii \"a.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */ +/* { dg-final { scan-assembler-times "ascii \"a1.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */ +/* { dg-final { scan-assembler-times "ascii \"d_instance.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */ + +static int b = 33; + +int a = 44; +int a1[2] = {22, 33}; + +struct d +{ + int d1; + int d2; +}; + +struct d d_instance; diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-pointers-1.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-pointers-1.c new file mode 100644 index 0000000..32da7bd --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-pointers-1.c @@ -0,0 +1,26 @@ +/* CTF generation for pointer types. + + In this testcase, two CTF pointer type records are expected + - int * + - struct foo_struct * + */ + +/* { dg-do compile ) */ +/* { dg-options "-O0 -gt -dA" } */ + +/* { dg-final { scan-assembler-times "ascii \"foo_struct.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */ +/* { dg-final { scan-assembler-times "ascii \"int.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */ +/* { dg-final { scan-assembler-times "\[\t \]0xe000000\[\t \]+\[^\n\]*ctt_info" 2 } } */ + +int b = 44; +int * a = &b; + +struct foo_struct +{ + int bar_mem_1; + int bar_mem_2; + float d; + struct foo_struct *next; +}; + +struct foo_struct * node; diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-skip-types-1.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-skip-types-1.c new file mode 100644 index 0000000..bd2935d --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-skip-types-1.c @@ -0,0 +1,33 @@ +/* CTF does not have representation for some types at this time. These types + are skipped in the CTF generation phase in the compiler. + + This testcase does NOT cover all skipped types exhaustively. */ + +/* { dg-do compile } */ +/* { dg-options "-gt" } */ + +#include + +typedef float La_x86_64_xmm __attribute__ ((__vector_size__ (16))); +La_x86_64_xmm a1; + +/* GCC also supports complex integer data types. */ +complex char a; +complex signed char b; +complex unsigned char c; +complex short int d; +complex short unsigned int e; +complex int f; +complex unsigned int g; +complex long int h; +complex long unsigned int i; +complex long long int j; + +enum gomp_schedule_type +{ + GFS_RUNTIME, + GFS_STATIC, + GFS_MONOTONIC = 0x80000000U +}; + +enum gomp_schedule_type gsch_type; diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-str-table-1.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-str-table-1.c new file mode 100644 index 0000000..2c5e352 --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-str-table-1.c @@ -0,0 +1,26 @@ +/* CTF String Table as generated by the compiler is expected to have only a + single empty string. Just an optimization by the compiler, it is not + mandated by the CTF format. */ + +/* { dg-do compile ) */ +/* { dg-options "-O0 -gt -dA" } */ +/* { dg-final { scan-assembler-times "ascii \".0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */ + +union wait +{ + int w_status; + struct + { + int __w_termsig; + int __w_coredump; + } __wait_terminated; + struct + { + int __w_stopval; + int __w_stopsig; + } __wait_stopped; +}; + +typedef union { union wait * __uptr; int * iptr; } __WAIT_STATUS; + +__WAIT_STATUS waitstatus; diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-struct-1.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-struct-1.c new file mode 100644 index 0000000..5d496d8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-struct-1.c @@ -0,0 +1,25 @@ +/* Test compilation of struct type. + + In this testcase, two CTF_K_STRUCT records are expected + struct a : ctt_info = 0x1a000004 (4 field members) + struct b : ctt_into = 0x1a000002 (2 field members) +*/ + +/* { dg-do compile ) */ +/* { dg-options "-O0 -gt -dA" } */ + +/* { dg-final { scan-assembler-times "\[\t \]0x1a000004\[\t \]+\[^\n\]*ctt_info" 1 } } */ +/* { dg-final { scan-assembler-times "\[\t \]0x1a000002\[\t \]+\[^\n\]*ctt_info" 1 } } */ +/* { dg-final { scan-assembler-times "ctm_name" 6 } } */ + +struct a +{ + int d1; + int d2; + float c; + struct b + { + int time; + int wall; + } b1; +} my_a; diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-struct-2.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-struct-2.c new file mode 100644 index 0000000..5b9c9c1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-struct-2.c @@ -0,0 +1,30 @@ +/* Test for compilation of self-referntial structs. + + Further, the compiler is expected to generate a single CTF struct type for + struct dmx_dtdef (due to Type de-duplication at CTF generation). */ + +/* { dg-do compile ) */ +/* { dg-options "-O0 -gt -dA" } */ +/* { dg-final { scan-assembler-times "ascii \"dmx_dtdef.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */ +/* { dg-final { scan-assembler-times "ascii \"dtd_name.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */ +/* { dg-final { scan-assembler-times "ascii \"dtd_type.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */ +/* { dg-final { scan-assembler-times "ascii \"dmx_dtdef_t.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */ + +struct link +{ + struct link * next; +} * s_link; + +typedef long dmx_id_t; + +typedef struct dmx_dtdef +{ + char * dtd_name; + dmx_id_t dtd_type; +} dmx_dtdef_t; + +typedef struct dmx_bundle +{ + dmx_id_t dmb_type; + dmx_dtdef_t * dmb_dtd; +} dmx_bundle_t; diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-struct-array-1.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-struct-array-1.c new file mode 100644 index 0000000..552be47 --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-struct-array-1.c @@ -0,0 +1,36 @@ +/* Test Compilation of mixed constructs containing structs and arrays. + + Further, the compiler is expected to generate a single CTF struct type for + struct cmodel (due to Type de-duplication at CTF generation). + + const qualifiers in fields of structs should be processed. It appears as a + no-name CTF record with appropriate ctt_info. In this testcase, 2 const + qualifier records are expected - const char and const struct cmodel. */ + +/* { dg-do compile ) */ +/* { dg-options "-O0 -gt -dA" } */ +/* { dg-final { scan-assembler-times "ascii \"cmodel.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */ +/* { dg-final { scan-assembler-times "ascii \"cname.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */ +/* { dg-final { scan-assembler-times "ascii \"cpointer.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */ +/* { dg-final { scan-assembler-times "ascii \"cmodel_t.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */ + +/* { dg-final { scan-assembler-times "\[\t \]0x32000000\[\t \]+\[^\n\]*ctt_info" 2 } } */ + +struct a +{ + int a1[2]; + struct { int b[3]; } a2; +}; + +typedef struct cmodel +{ + const char *cname; + int ccode; + int cpointer; +} cmodel_t; + +static const cmodel_t _models[] = { + {"ILP32", 0, 4}, + {"LP64", 0, 8}, + {"", 0, 0} +}; diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-typedef-1.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-typedef-1.c new file mode 100644 index 0000000..227d7db --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-typedef-1.c @@ -0,0 +1,23 @@ +/* CTF_K_TYPEDEF record generation. + + In this testcase, 7 typedef records are expected. */ + +/* { dg-do compile ) */ +/* { dg-options "-O0 -gt -dA" } */ + +/* { dg-final { scan-assembler-times "0x2a000000\[\t \]+\[^\n\]*ctt_info" 7 } } */ + +typedef int my_int; +typedef int bar_int; +typedef int foo_int; + +typedef struct { int a[2]; } my_array; + +typedef const int CINT; +typedef const int * CINTP; + +typedef struct my_node +{ + int flags; + char value; +} my_node_t; diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-typedef-struct-1.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-typedef-struct-1.c new file mode 100644 index 0000000..a7e5249 --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-typedef-struct-1.c @@ -0,0 +1,12 @@ +/* { dg-do compile ) */ +/* { dg-options "-O0 -gt -dA" } */ + +typedef struct my_int +{ + int upper; + int lower; + struct bitmask + { + int flags; + } my_mask; +} my_int_t; diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-union-1.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-union-1.c new file mode 100644 index 0000000..59b4cb7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-union-1.c @@ -0,0 +1,14 @@ +/* CTF generation for union type. */ + +/* { dg-do compile ) */ +/* { dg-options "-O0 -gt -dA" } */ +/* { dg-final { scan-assembler-times "\[\t \]0x1e000004\[\t \]+\[^\n\]*ctt_info" 1 } } */ +/* { dg-final { scan-assembler-times "ctm_name" 4 } } */ + +union c +{ + int c1; + int c2; + int c3; + int c4; +} my_u_c; diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-variables-1.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-variables-1.c new file mode 100644 index 0000000..a2e2557 --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-variables-1.c @@ -0,0 +1,25 @@ +/* CTF generation for global variables. + + In this testcase, 7 records in the variable info section are expected. */ + +/* { dg-do compile ) */ +/* { dg-options "-O0 -gt -dA" } */ + +/* { dg-final { scan-assembler-times "ctv_name" 7 } } */ + +float var1; +double var2; +long double var3; + +char ascii = 'a'; + +int a = 33; +int a1[2] = {22, 33}; + +struct d +{ + int d1; + int d2; +}; + +struct d d_instance; From patchwork Mon Sep 9 04:28:21 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Indu Bhagat X-Patchwork-Id: 1159597 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-508569-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=oracle.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="YoWkJ5D2"; dkim=pass (2048-bit key; unprotected) header.d=oracle.com header.i=@oracle.com header.b="Tl+8anL3"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 46RZvm09fVz9s4Y for ; Mon, 9 Sep 2019 14:30:11 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:subject:date:message-id:in-reply-to:references; q=dns; s= default; b=NnUf6q+Q/w4/bFxBqx5KFguFvDTF01CY9HVWAOb9cwSiAxVjJs4+e EoNX6Nr1IkpeXwKG+nWf8NgT91vk+l3LwaFpeXzU7h4EM8KOhC7ejNE8z+1/wsQ/ QShFH67HM7beWj5Sr8x3et6a909iqL0dFohB8xlHtYqFXHu7s7bGxM= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:subject:date:message-id:in-reply-to:references; s=default; bh=s7OvGXwyzT2Jm3ZTMj0GVaBvi0A=; b=YoWkJ5D2aIRo4WTAhD3LZ/hTzgew KE2ZdmDa2pneBkmo5pXvQSwF0VOEqgC3sGCUbqa5AJgybCViI2lOpBwTPv58SfAe ewqH3C6UsoJxzsyW6hNlVpToNVXxYgjikkHzg6cKwpMlmYpgC+8GuS90aAFhxBDv GTzX0lov4QR+o8I= Received: (qmail 110474 invoked by alias); 9 Sep 2019 04:28:58 -0000 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 Received: (qmail 110410 invoked by uid 89); 9 Sep 2019 04:28:57 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-21.7 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, SPF_HELO_PASS, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 spammy=rename, HX-Languages-Length:785, Copy X-HELO: userp2130.oracle.com Received: from userp2130.oracle.com (HELO userp2130.oracle.com) (156.151.31.86) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 09 Sep 2019 04:28:56 +0000 Received: from pps.filterd (userp2130.oracle.com [127.0.0.1]) by userp2130.oracle.com (8.16.0.27/8.16.0.27) with SMTP id x894NpvP004463 for ; Mon, 9 Sep 2019 04:28:54 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oracle.com; h=from : to : subject : date : message-id : in-reply-to : references; s=corp-2019-08-05; bh=BqORXCZ0FGw+A9akJLb/DjvB6ZqCI80+XJdlUL0r87I=; b=Tl+8anL3yvpIW71BdDNeMFKFx2VnrwFNbuz7EGG+pPuR8sAtoez8Ykfn0ShZliYwiq35 z2Y1brq7PvIi8Mj7BnvlEAguEUcWYKX3GPqoQ3/1ccwRJNJZfQpzQ4cbAwkEaTdXxmkw 1aBad/Z8qIj7kG/6mS5Bvgep6EhVLK2VAZYp3xmjnUl2ojwnGfeiP2zQtiwfpHoR4UgG r2ery1yQlDv9yPqbkyhUrWJYfX30FIk85D9EJK05SVPtYOGXYMO62gxSqM1LNI9Fh0Va b4e1Upf2oGMWj2E1lzpILTxonM4P56/nkW3tXHd5zgExJRc4pVXhjwd8zw/jRvy9tmIM 0A== Received: from aserp3030.oracle.com (aserp3030.oracle.com [141.146.126.71]) by userp2130.oracle.com with ESMTP id 2uw1m8hhjq-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK) for ; Mon, 09 Sep 2019 04:28:54 +0000 Received: from pps.filterd (aserp3030.oracle.com [127.0.0.1]) by aserp3030.oracle.com (8.16.0.27/8.16.0.27) with SMTP id x894SnxS062990 for ; Mon, 9 Sep 2019 04:28:53 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by aserp3030.oracle.com with ESMTP id 2uv2ky9hjr-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK) for ; Mon, 09 Sep 2019 04:28:50 +0000 Received: from abhmp0002.oracle.com (abhmp0002.oracle.com [141.146.116.8]) by aserv0121.oracle.com (8.14.4/8.13.8) with ESMTP id x894SVrW016106 for ; Mon, 9 Sep 2019 04:28:33 GMT Received: from ibhagatpc.us.oracle.com (/10.65.144.100) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Sun, 08 Sep 2019 21:28:30 -0700 From: Indu Bhagat To: gcc-patches@gcc.gnu.org Subject: [PATCH,RFC,V5 6/6] Handle CTF sections when LTO is enabled Date: Sun, 8 Sep 2019 21:28:21 -0700 Message-Id: <1568003301-11457-7-git-send-email-indu.bhagat@oracle.com> In-Reply-To: <1568003301-11457-1-git-send-email-indu.bhagat@oracle.com> References: <1568003301-11457-1-git-send-email-indu.bhagat@oracle.com> libiberty/ChangeLog: * simple-object.c (handle_lto_debug_sections): Copy CTF section. --- libiberty/ChangeLog | 5 +++++ libiberty/simple-object.c | 3 +++ 2 files changed, 8 insertions(+) diff --git a/libiberty/simple-object.c b/libiberty/simple-object.c index b00c265..96bdcf8 100644 --- a/libiberty/simple-object.c +++ b/libiberty/simple-object.c @@ -298,6 +298,9 @@ handle_lto_debug_sections (const char *name, int rename) COMDAT sections in objects produced by GCC. */ else if (strcmp (name, ".comment") == 0) return strcpy (newname, name); + /* Copy over .ctf section under the same name if present. */ + else if (strcmp (name, ".ctf") == 0) + return strcpy (newname, name); free (newname); return NULL; }