From patchwork Thu Sep 11 09:18:58 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Marc_Poulhi=C3=A8s?= X-Patchwork-Id: 120045 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 162683858D35 for ; Thu, 11 Sep 2025 09:35:12 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 162683858D35 Authentication-Results: sourceware.org; dkim=pass (2048-bit key, secure) header.d=adacore.com header.i=@adacore.com header.a=rsa-sha256 header.s=google header.b=LW1eD1Sl X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-wm1-x32a.google.com (mail-wm1-x32a.google.com [IPv6:2a00:1450:4864:20::32a]) by sourceware.org (Postfix) with ESMTPS id 353B83858D26 for ; Thu, 11 Sep 2025 09:19:38 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 353B83858D26 Authentication-Results: sourceware.org; dmarc=pass (p=quarantine dis=none) header.from=adacore.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=adacore.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 353B83858D26 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2a00:1450:4864:20::32a ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1757582378; cv=none; b=cilwg4D3imxsg6k97hMHnx1SO826lLGsx8sOl97lLbKNlwy/IaAOCOE2GX1dJRAplyRmAvO2r++s588M3IbmPxKmH1QHp66v/f2Gibzm3O7eqR0zwgqNW+Fl/jZE9LNzHNXhK4+A2ujQKeFmkB6RLj2YKodxnt/hMFJvzkpG/04= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1757582378; c=relaxed/simple; bh=umsD82I7sVU5ENO2qS6XxpWSSGoMW6qxixR6mHKZGm4=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=P22s5SufAyS9ibvO9KDiMImL3EhT90DCa8fX14jD1r0D4eH9egn/tT71YLnHc6iAXCpJEWS1Z4Sp5BLpkoLqAfM/EhOHGokP7cH/X8It9jlyvsmMINBWp/K3OqI85lyvDVPVA7PvXiu/9peJCFw6gzFijcLgT5z7Jz4sK2rV4eA= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 353B83858D26 Received: by mail-wm1-x32a.google.com with SMTP id 5b1f17b1804b1-45dec1ae562so4372035e9.1 for ; Thu, 11 Sep 2025 02:19:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=adacore.com; s=google; t=1757582376; x=1758187176; darn=gcc.gnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=NfcLEfBL+DtCL3o6m7MKZE1fjoj6/EgedaNwLS9mbpo=; b=LW1eD1SlDhc05NEgYkN568lfo+PFv+eUj16Wt2/9HLFqHmKjPj5FWOrzls4+MGhiF/ bfCrDqFVXNr4PqX6ylrRTK1zgy9XyGHJk0cfJuDQs8Ai/0YR7yAEAlOJ/9KYGWQ8eO8S j4HwsZgrgCIh2jQjDclXoGUFR8OblznVh/N4lXV0hFISg4GSCl9eq8D7gV88y03XVlKE TDQdLEuSJHAZh9TF0S01Uq6xA15vgQOHniI/M0Dqq9RzqIQws4Ux9Y7ccg5uv00FcloE WRrqA+pbNC8X07Y7326WdWvPDeaWJfGbTlyfwEatk1c5kp7EdAOeJMKe7xAAVC1YF26C YHfA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1757582376; x=1758187176; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=NfcLEfBL+DtCL3o6m7MKZE1fjoj6/EgedaNwLS9mbpo=; b=LZEC5ORGf9pr0+lkv3LcHc68enPWStFer106LoHPhof48HVFpHnNZk2lKM0LpYq3Z2 karNMVxzFR9YiAww+zDNqlCFgKRlWkChjiYf8iSAxc5nokpSn5HF1UUBJzA/2jsUlm9t 2Vq8xpLiVecjEk0T56WX3DBdx2ZRf+TYwYekzbdGV3UZiH0pjdDZGmvRwgdC4enf6ma+ LGW27eOsdZ3IOPl1EJ3d8cTr/nWijM8lUXsaLF30mvqC+YWxG7xT7Gmw10K8O0gJGDpS 9lEar9zi/jbUn47f1EqIMDztgR2rbGjeb3HYYQa6V4MeF5Q0Bq5NeaVYFKlxE8IPeLjZ Xs6A== X-Gm-Message-State: AOJu0YzFvaD3a83i2z0KU8ssZ9s7KybEraRoqJzpHW5LwrRPLzHCEwMq viGwJWJ2LsIkBDL3NAWsoi6kc6Hu+ZXwa5AEHDqA2HANX/WPMSFVDIdo0KSgIl6lk0lqiC19uSc IwHw= X-Gm-Gg: ASbGncsxLG8sJreBVUhL8StReOYXprGooO533mrCWSYSLzDvQ/6tmJx6v8A9Q30csP5 XBcQRHKqwCFiRNmQOPKLLn0H7rbrQwRc44Az5Vybnc9/qQEnr927U0dZ3xQMwvWxPfoBbUzg9WE X5WGMJZgvX0J0qTUpVl/9e+wfMARngKV86mEsk26Blzj1sukkLbrlg0Aj6FZnvhxotTYjPSD08u TGGgYzj83y/KNa4Zc4WbY037WTGd4e3i/DxbF0x7cfmFbTatOXdljXFTdh1TmRaiP+D70bO+sZ2 fsJ2Cho2ZaixzFvx+nzTwy896KshxbrZ+oUh849D9p7iFVoUlABmug3Pwv7d4GO0eO/JTnFwa23 EkfHBGk3Oz8aBRFa865lr/WPFf/sX0fSQc8AXkaUfFFm+9RCOdEyXAOKOVWhDH+mVrS90I4dHHi Oe9QEXVaHJwI4b4TsnT6O84ajUn5sKZagJYeLV4INkxj++FgWU X-Google-Smtp-Source: AGHT+IGpJHTPAJ6MoraGAiXjCTtUPe9LznOkI6mxFbhgzFwL97UmWMit/mBGzOKMfM76D8ClUNCjjA== X-Received: by 2002:a05:6000:40c9:b0:3da:d015:bf84 with SMTP id ffacd0b85a97d-3e64196afd4mr18385764f8f.25.1757582376318; Thu, 11 Sep 2025 02:19:36 -0700 (PDT) Received: from poulhies-Precision-5550.telnowedge.local (lmontsouris-659-1-24-67.w81-250.abo.wanadoo.fr. [81.250.175.67]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-3e7607cd27dsm1649971f8f.41.2025.09.11.02.19.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 11 Sep 2025 02:19:35 -0700 (PDT) From: =?utf-8?q?Marc_Poulhi=C3=A8s?= To: gcc-patches@gcc.gnu.org Cc: Eric Botcazou Subject: [COMMITTED 26/31] ada: Implement overflow checking for unsigned types Date: Thu, 11 Sep 2025 11:18:58 +0200 Message-ID: <20250911091904.1505690-26-poulhies@adacore.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250911091904.1505690-1-poulhies@adacore.com> References: <20250911091904.1505690-1-poulhies@adacore.com> MIME-Version: 1.0 X-Spam-Status: No, score=-13.8 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces~patchwork=sourceware.org@gcc.gnu.org From: Eric Botcazou The implementation is essentially mirrored from the one for signed types. gcc/ada/ChangeLog: * gcc-interface/gigi.h (standard_datatypes): Add ADT_uns_mulv64_decl and ADT_uns_mulv128_decl. (uns_mulv64_decl): New macro. (uns_mulv128_decl): Likewise. * gcc-interface/trans.cc (gigi): Create the uns_mulv64_decl and uns_mulv128_decl declarations. (gnat_to_gnu) : Perform an overflow check for unsigned integer addition, subtraction and multiplication if required. : Perform an overflow check for unsigned integer negation if required. (build_unary_op_trapv): Add support for unsigned types. (build_binary_op_trapv): Likewise. : Perform the check if the LHS is zero in the signed case as well. Tested on x86_64-pc-linux-gnu, committed on master. --- gcc/ada/gcc-interface/gigi.h | 8 ++- gcc/ada/gcc-interface/trans.cc | 103 +++++++++++++++++++++++---------- 2 files changed, 79 insertions(+), 32 deletions(-) diff --git a/gcc/ada/gcc-interface/gigi.h b/gcc/ada/gcc-interface/gigi.h index 0345111fb85f..45b1bfd23e3a 100644 --- a/gcc/ada/gcc-interface/gigi.h +++ b/gcc/ada/gcc-interface/gigi.h @@ -388,11 +388,13 @@ enum standard_datatypes /* Function declaration node for run-time reallocation function. */ ADT_realloc_decl, - /* Function decl node for 64-bit multiplication with overflow checking. */ + /* Function decl nodes for 64-bit multiplication with overflow checking. */ ADT_mulv64_decl, + ADT_uns_mulv64_decl, - /* Function decl node for 128-bit multiplication with overflow checking. */ + /* Function decl nodes for 128-bit multiplication with overflow checking. */ ADT_mulv128_decl, + ADT_uns_mulv128_decl, /* Identifier for the name of the _Parent field in tagged record types. */ ADT_parent_name_id, @@ -455,7 +457,9 @@ extern GTY(()) tree gnat_raise_decls_ext[(int) LAST_REASON_CODE + 1]; #define free_decl gnat_std_decls[(int) ADT_free_decl] #define realloc_decl gnat_std_decls[(int) ADT_realloc_decl] #define mulv64_decl gnat_std_decls[(int) ADT_mulv64_decl] +#define uns_mulv64_decl gnat_std_decls[(int) ADT_uns_mulv64_decl] #define mulv128_decl gnat_std_decls[(int) ADT_mulv128_decl] +#define uns_mulv128_decl gnat_std_decls[(int) ADT_uns_mulv128_decl] #define parent_name_id gnat_std_decls[(int) ADT_parent_name_id] #define not_handled_by_others_name_id \ gnat_std_decls[(int) ADT_not_handled_by_others_name_id] diff --git a/gcc/ada/gcc-interface/trans.cc b/gcc/ada/gcc-interface/trans.cc index fd1d39cd0f55..3c6e87e52c0a 100644 --- a/gcc/ada/gcc-interface/trans.cc +++ b/gcc/ada/gcc-interface/trans.cc @@ -319,7 +319,7 @@ gigi (Node_Id gnat_root, { Node_Id gnat_iter; Entity_Id gnat_literal; - tree t, ftype, int64_type; + tree t, ftype; struct elab_info *info; int i; @@ -466,7 +466,7 @@ gigi (Node_Id gnat_root, false, NULL, Empty); /* This is used for 64-bit multiplication with overflow checking. */ - int64_type = gnat_type_for_size (64, 0); + tree int64_type = gnat_type_for_size (64, 0); mulv64_decl = create_subprog_decl (get_identifier ("__gnat_mulv64"), NULL_TREE, build_function_type_list (int64_type, int64_type, @@ -475,6 +475,15 @@ gigi (Node_Id gnat_root, false, NULL, Empty); strub_make_callable (mulv64_decl); + tree uint64_type = gnat_type_for_size (64, 1); + uns_mulv64_decl + = create_subprog_decl (get_identifier ("__gnat_uns_mulv64"), NULL_TREE, + build_function_type_list (uint64_type, uint64_type, + uint64_type, NULL_TREE), + NULL_TREE, is_default, true, true, true, false, + false, NULL, Empty); + strub_make_callable (uns_mulv64_decl); + if (Enable_128bit_Types) { tree int128_type = gnat_type_for_size (128, 0); @@ -487,6 +496,17 @@ gigi (Node_Id gnat_root, NULL_TREE, is_default, true, true, true, false, false, NULL, Empty); strub_make_callable (mulv128_decl); + + tree uint128_type = gnat_type_for_size (128, 1); + uns_mulv128_decl + = create_subprog_decl (get_identifier ("__gnat_uns_mulv128"), NULL_TREE, + build_function_type_list (uint128_type, + uint128_type, + uint128_type, + NULL_TREE), + NULL_TREE, is_default, true, true, true, false, + false, NULL, Empty); + strub_make_callable (uns_mulv128_decl); } /* Name of the _Parent field in tagged record types. */ @@ -7504,12 +7524,11 @@ gnat_to_gnu (Node_Id gnat_node) gnu_max_shift = convert (gnu_type, gnu_max_shift); } - /* For signed integer addition, subtraction and multiplication, do an + /* For integer addition, subtraction and multiplication, perform an overflow check if required. */ - if (Do_Overflow_Check (gnat_node) - && (code == PLUS_EXPR || code == MINUS_EXPR || code == MULT_EXPR) - && !TYPE_UNSIGNED (gnu_type) - && !FLOAT_TYPE_P (gnu_type)) + if ((code == PLUS_EXPR || code == MINUS_EXPR || code == MULT_EXPR) + && !FLOAT_TYPE_P (gnu_type) + && Do_Overflow_Check (gnat_node)) gnu_result = build_binary_op_trapv (code, gnu_type, gnu_lhs, gnu_rhs, gnat_node); @@ -7590,11 +7609,11 @@ gnat_to_gnu (Node_Id gnat_node) gnu_expr = gnat_to_gnu (Right_Opnd (gnat_node)); gnu_result_type = get_unpadded_type (Etype (gnat_node)); - /* For signed integer negation and absolute value, do an overflow check + /* For integer negation and absolute value, perform an overflow check if required. */ - if (Do_Overflow_Check (gnat_node) - && !TYPE_UNSIGNED (gnu_result_type) - && !FLOAT_TYPE_P (gnu_result_type)) + if ((gnu_codes[kind] == NEGATE_EXPR || gnu_codes[kind] == ABS_EXPR) + && !FLOAT_TYPE_P (gnu_result_type) + && Do_Overflow_Check (gnat_node)) gnu_result = build_unary_op_trapv (gnu_codes[kind], gnu_result_type, gnu_expr, gnat_node); @@ -9959,12 +9978,25 @@ build_unary_op_trapv (enum tree_code code, tree gnu_type, tree operand, { gcc_assert (code == NEGATE_EXPR || code == ABS_EXPR); + tree gnu_expr, check; + operand = gnat_protect_expr (operand); - return emit_check (build_binary_op (EQ_EXPR, boolean_type_node, - operand, TYPE_MIN_VALUE (gnu_type)), - build_unary_op (code, gnu_type, operand), - CE_Overflow_Check_Failed, gnat_node); + gnu_expr = build_unary_op (code, gnu_type, operand); + + if (TYPE_UNSIGNED (gnu_type)) + { + if (code == ABS_EXPR) + return gnu_expr; + else + check = build_binary_op (NE_EXPR, boolean_type_node, + operand, TYPE_MIN_VALUE (gnu_type)); + } + else + check = build_binary_op (EQ_EXPR, boolean_type_node, + operand, TYPE_MIN_VALUE (gnu_type)); + + return emit_check (check, gnu_expr, CE_Overflow_Check_Failed, gnat_node); } /* Make a binary operation of kind CODE using build_binary_op, but guard @@ -10017,21 +10049,29 @@ build_binary_op_trapv (enum tree_code code, tree gnu_type, tree left, /* Never inline a 64-bit mult for a 32-bit target, it's way too long. */ if (code == MULT_EXPR && precision == 64 && BITS_PER_WORD < 64) { - tree int64 = gnat_type_for_size (64, 0); + tree int64 = gnat_type_for_size (64, TYPE_UNSIGNED (gnu_type)); Check_Restriction_No_Dependence_On_System (Name_Arith_64, gnat_node); - return convert (gnu_type, build_call_n_expr (mulv64_decl, 2, - convert (int64, lhs), - convert (int64, rhs))); + return + convert (gnu_type, build_call_n_expr (TYPE_UNSIGNED (gnu_type) + ? uns_mulv64_decl + : mulv64_decl, + 2, + convert (int64, lhs), + convert (int64, rhs))); } /* Likewise for a 128-bit mult and a 64-bit target. */ else if (code == MULT_EXPR && precision == 128 && BITS_PER_WORD < 128) { - tree int128 = gnat_type_for_size (128, 0); + tree int128 = gnat_type_for_size (128, TYPE_UNSIGNED (gnu_type)); Check_Restriction_No_Dependence_On_System (Name_Arith_128, gnat_node); - return convert (gnu_type, build_call_n_expr (mulv128_decl, 2, - convert (int128, lhs), - convert (int128, rhs))); + return + convert (gnu_type, build_call_n_expr (TYPE_UNSIGNED (gnu_type) + ? uns_mulv128_decl + : mulv128_decl, + 2, + convert (int128, lhs), + convert (int128, rhs))); } enum internal_fn icode; @@ -10065,7 +10105,7 @@ build_binary_op_trapv (enum tree_code code, tree gnu_type, tree left, } /* If one operand is a constant, we expose the overflow condition to enable - a subsequent simplication or even elimination. */ + a subsequent simplification or even elimination. */ switch (code) { case PLUS_EXPR: @@ -10085,21 +10125,24 @@ build_binary_op_trapv (enum tree_code code, tree gnu_type, tree left, break; case MINUS_EXPR: - if (TREE_CODE (lhs) == INTEGER_CST) + if (TREE_CODE (lhs) == INTEGER_CST && TYPE_UNSIGNED (gnu_type)) + /* In the unsigned case, overflow when rhs > lhs - type_min. */ + check = build_binary_op (GT_EXPR, boolean_type_node, rhs, + build_binary_op (MINUS_EXPR, gnu_type, + lhs, type_min)); + else if (TREE_CODE (lhs) == INTEGER_CST) { sgn = tree_int_cst_sgn (lhs); - if (sgn > 0) - /* When lhs > 0, overflow when rhs < lhs - type_max. */ + if (sgn >= 0) + /* When lhs >= 0, overflow when rhs < lhs - type_max. */ check = build_binary_op (LT_EXPR, boolean_type_node, rhs, build_binary_op (MINUS_EXPR, gnu_type, lhs, type_max)); - else if (sgn < 0) + else /* When lhs < 0, overflow when rhs > lhs - type_min. */ check = build_binary_op (GT_EXPR, boolean_type_node, rhs, build_binary_op (MINUS_EXPR, gnu_type, lhs, type_min)); - else - return gnu_expr; } else {