From patchwork Sat Jun 27 10:45:51 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiawei X-Patchwork-Id: 137935 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from vm01.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 0BF5C4BA23C2 for ; Sat, 27 Jun 2026 10:48:18 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 0BF5C4BA23C2 X-Original-To: binutils@sourceware.org Delivered-To: binutils@sourceware.org Received: from cstnet.cn (smtp21.cstnet.cn [159.226.251.21]) by sourceware.org (Postfix) with ESMTPS id AECA94BA2E2F for ; Sat, 27 Jun 2026 10:46:26 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org AECA94BA2E2F Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=iscas.ac.cn Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=iscas.ac.cn ARC-Filter: OpenARC Filter v1.0.0 sourceware.org AECA94BA2E2F Authentication-Results: sourceware.org; arc=none smtp.remote-ip=159.226.251.21 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1782557187; cv=none; b=LaakEL2sA8MQSkox+sk1Drm66HW2PsDOz2QLgOuFF/lT/l9V5vy1HV2OuzyF7zCM67D7242MEcNdFD1A6JfKuUa3y9/VHOlt/SeVZ3BrsAN7J5wgFVb8aGRtTvu8PjiyeeFcDaFekDcQ7l6jXcPlkNpXrtGzgYDz7FTa36Iokjc= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1782557187; c=relaxed/simple; bh=FvqQDJjgvn8GiBv5iEBYyrTnHgp1bvPtGxKDEeNuI5Q=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=JH/GF4ptzzpzhwknBBgmWqbKmzF9lq/Ktag08TKqOx0iOWycZcLYnpi7K/ClxWU5EWJ37mT0OZvIZq6bW3czouTr4auO3W85nyGXyxkw9d+NKC93R79BRyfM0vArF0anwkm7Nef8qHA/TuoJg24n+EpJJ0YIOFuqznq2rU8ou+0= ARC-Authentication-Results: i=1; sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org AECA94BA2E2F Received: from localhost.localdomain (unknown [157.0.80.168]) by APP-01 (Coremail) with SMTP id qwCowACXMcr6qT9qMtWNAw--.25411S3; Sat, 27 Jun 2026 18:46:20 +0800 (CST) From: Jiawei To: binutils@sourceware.org Cc: nelson@rivosinc.com, jbeulich@suse.com, jeremy.bennett@embecosm.com, kito.cheng@sifive.com, mary.bennett@embecosm.com, nandni.jamnadas@embecosm.com, charlie.keaney@embecosm.com, hau.hsu@sifive.com, jerry.zhangjian@sifive.com, sinan.lin@linux.alibaba.com, Jiawei Subject: [RFC PATCH 1/5] RISC-V: Add Zcmt table-jump relocation definitions Date: Sat, 27 Jun 2026 18:45:51 +0800 Message-ID: <20260627104555.331493-2-jiawei@iscas.ac.cn> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260627104555.331493-1-jiawei@iscas.ac.cn> References: <20260627104555.331493-1-jiawei@iscas.ac.cn> MIME-Version: 1.0 X-CM-TRANSID: qwCowACXMcr6qT9qMtWNAw--.25411S3 X-Coremail-Antispam: 1UD129KBjvJXoWxWrWxAw17CrWxCF1kAry7ZFb_yoWrAFW3pF s8JrWruFs5CryxGwsaqF4UKrWftw4Fkr4ay3y3Zw4UAr4DJr40qF4Dt3W5Ca1DXF4vqrya vF9rK3y5uw4avrDanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUQI14x267AKxVW5JVWrJwAFc2x0x2IEx4CE42xK8VAvwI8IcIk0 rVWrJVCq3wAFIxvE14AKwVWUJVWUGwA2048vs2IY020E87I2jVAFwI0_Jr4l82xGYIkIc2 x26xkF7I0E14v26r4j6ryUM28lY4IEw2IIxxk0rwA2F7IY1VAKz4vEj48ve4kI8wA2z4x0 Y4vE2Ix0cI8IcVAFwI0_Gr0_Xr1l84ACjcxK6xIIjxv20xvEc7CjxVAFwI0_Gr0_Cr1l84 ACjcxK6I8E87Iv67AKxVW0oVCq3wA2z4x0Y4vEx4A2jsIEc7CjxVAFwI0_GcCE3s1le2I2 62IYc4CY6c8Ij28IcVAaY2xG8wAqx4xG64xvF2IEw4CE5I8CrVC2j2WlYx0E2Ix0cI8IcV AFwI0_Jr0_Jr4lYx0Ec7CjxVAajcxG14v26r1j6r4UMcIj6I8E87Iv67AKxVWUJVW8JwAm 72CE4IkC6x0Yz7v_Jr0_Gr1lF7xvr2IYc2Ij64vIr41lF7I21c0EjII2zVCS5cI20VAGYx C7M4IIrI8v6xkF7I0E8cxan2IY04v7MxkF7I0En4kS14v26r1q6r43MxAIw28IcxkI7VAK I48JMxC20s026xCaFVCjc4AY6r1j6r4UMI8I3I0E5I8CrVAFwI0_Jr0_Jr4lx2IqxVCjr7 xvwVAFwI0_JrI_JrWlx4CE17CEb7AF67AKxVWUtVW8ZwCIc40Y0x0EwIxGrwCI42IY6xII jxv20xvE14v26r1j6r1xMIIF0xvE2Ix0cI8IcVCY1x0267AKxVW8JVWxJwCI42IY6xAIw2 0EY4v20xvaj40_Jr0_JF4lIxAIcVC2z280aVAFwI0_Jr0_Gr1lIxAIcVC2z280aVCY1x02 67AKxVW8JVW8JrUvcSsGvfC2KfnxnUUI43ZEXa7VUUfcTJUUUUU== X-Originating-IP: [157.0.80.168] X-CM-SenderInfo: 5mld4v3l6l2u1dvotugofq/1tbiCRILAGo-k+En3wAAsP X-Spam-Status: No, score=-11.1 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, SPF_HELO_PASS, SPF_PASS, TXREP shortcircuit=no autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on sourceware.org X-BeenThere: binutils@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Binutils mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: binutils-bounces~patchwork=sourceware.org@sourceware.org Add a ZCMT table jump relaxation pass in the linker, the ELF relocation number, opcode constants, and RISC-V BFD parameter state needed by linker table-jump relaxation. bfd/ChangeLog: * elfxx-riscv.c: Add TABLE_JUMP howto. * elfxx-riscv.h (struct riscv_elf_params): Add relax_zcmt field. (enum riscv_relax_pass): New enum. (enum jvt_profiling_trip): Ditto. include/ChangeLog: * elf/riscv.h (R_RISCV_TABLE_JUMP): New reloc number. (RISCV_TABLE_JUMP_BASE_SYMBOL): New symbol name. (TABLE_JUMP_SEC_NAME): New section name. * opcode/riscv.h (ZCMT_TOTAL_ENTRIES): New Zcmt constants. (ZCMT_JT_BEGIN): Ditto. (ZCMT_JT_END): Ditto. (ZCMT_JT_NUM_ENTRIES): Ditto. (ZCMT_JALT_BEGIN): Ditto. (ZCMT_JALT_END): Ditto. (ZCMT_JALT_NUM_ENTRIES): Ditto. --- bfd/elfxx-riscv.c | 4 ++++ bfd/elfxx-riscv.h | 21 +++++++++++++++++++++ include/elf/riscv.h | 5 +++++ include/opcode/riscv.h | 9 +++++++++ 4 files changed, 39 insertions(+) diff --git a/bfd/elfxx-riscv.c b/bfd/elfxx-riscv.c index 961c44a9206..615f644d336 100644 --- a/bfd/elfxx-riscv.c +++ b/bfd/elfxx-riscv.c @@ -961,6 +961,10 @@ static const reloc_howto_type howto_table_internal[] = 0, /* src_mask */ ENCODE_STYPE_IMM (-1U), /* dst_mask */ false), /* pcrel_offset */ + + /* R_RISCV_TABLE_JUMP is linker-internal. It is consumed before final + relocations are emitted and must never become psABI-visible. */ + EMPTY_HOWTO (0), }; /* A mapping from BFD reloc types to RISC-V ELF reloc types. */ diff --git a/bfd/elfxx-riscv.h b/bfd/elfxx-riscv.h index e57e90462f8..6adf1d6d0ca 100644 --- a/bfd/elfxx-riscv.h +++ b/bfd/elfxx-riscv.h @@ -44,6 +44,8 @@ struct riscv_elf_params bool relax_gp; /* Whether to check if SUB_ULEB128 relocation has non-zero addend. */ bool check_uleb128; + /* Whether to relax code sequences for Zcmt. */ + bool relax_zcmt; }; extern void riscv_elf32_set_options (struct bfd_link_info *, @@ -101,6 +103,25 @@ typedef struct bool check_unknown_prefixed_ext; } riscv_parse_subset_t; +/* List the relaxation passes. */ +enum riscv_relax_pass +{ + RELAX_PASS_SHORTEN_LUI_CALL_TRREL_PCREL, + RELAX_PASS_CAN_BE_DISABLED = RELAX_PASS_SHORTEN_LUI_CALL_TRREL_PCREL, + RELAX_PASS_TABLE_JUMP_PROFILING, + RELAX_PASS_ALIGNMENT, + RELAX_PASS_END, +}; + +/* Trips for jvt profiling relaxation pass. */ +enum jvt_profiling_trip +{ + JVT_PROFILING_RECORD_SYM, + JVT_PROFILING_RANK, + JVT_PROFILING_DETERMINE, + JVT_PROFILING_TRIM, +}; + extern bool riscv_parse_subset (riscv_parse_subset_t *, const char *); diff --git a/include/elf/riscv.h b/include/elf/riscv.h index f6ca3d4acd8..02a0184b7ee 100644 --- a/include/elf/riscv.h +++ b/include/elf/riscv.h @@ -105,6 +105,7 @@ END_RELOC_NUMBERS (R_RISCV_max) #define R_RISCV_GPREL_S (R_RISCV_max + 4) #define R_RISCV_TPREL_I (R_RISCV_max + 5) #define R_RISCV_TPREL_S (R_RISCV_max + 6) +#define R_RISCV_TABLE_JUMP (R_RISCV_max + 7) /* Processor specific flags for the ELF header e_flags field. */ @@ -132,6 +133,10 @@ END_RELOC_NUMBERS (R_RISCV_max) /* The name of the global pointer symbol. */ #define RISCV_GP_SYMBOL "__global_pointer$" +#define RISCV_TABLE_JUMP_BASE_SYMBOL "__jvt_base$" + +#define TABLE_JUMP_SEC_NAME ".riscv.jvt" + /* Processor specific dynamic array tags. */ #define DT_RISCV_VARIANT_CC (DT_LOPROC + 1) diff --git a/include/opcode/riscv.h b/include/opcode/riscv.h index b4587976ea2..5e1157e3e50 100644 --- a/include/opcode/riscv.h +++ b/include/opcode/riscv.h @@ -698,6 +698,15 @@ struct riscv_opcode disassembler, and requires special treatment by the assembler. */ #define INSN_MACRO 0xffffffff +/* Define Zcmt jump table constants. */ +#define ZCMT_TOTAL_ENTRIES 256 +#define ZCMT_JT_BEGIN 0 +#define ZCMT_JT_END 31 +#define ZCMT_JT_NUM_ENTRIES (ZCMT_JT_END - ZCMT_JT_BEGIN + 1) +#define ZCMT_JALT_BEGIN (ZCMT_JT_END + 1) +#define ZCMT_JALT_END (ZCMT_TOTAL_ENTRIES - 1) +#define ZCMT_JALT_NUM_ENTRIES (ZCMT_JALT_END - ZCMT_JALT_BEGIN + 1) + /* This is a list of macro expanded instructions. */ enum { From patchwork Sat Jun 27 10:45:52 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiawei X-Patchwork-Id: 137936 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from vm01.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 129004BA23CE for ; Sat, 27 Jun 2026 10:48:35 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 129004BA23CE X-Original-To: binutils@sourceware.org Delivered-To: binutils@sourceware.org Received: from cstnet.cn (smtp21.cstnet.cn [159.226.251.21]) by sourceware.org (Postfix) with ESMTPS id EE35E4BA2E32 for ; Sat, 27 Jun 2026 10:46:27 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org EE35E4BA2E32 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=iscas.ac.cn Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=iscas.ac.cn ARC-Filter: OpenARC Filter v1.0.0 sourceware.org EE35E4BA2E32 Authentication-Results: sourceware.org; arc=none smtp.remote-ip=159.226.251.21 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1782557189; cv=none; b=HzPHy3ecHhNiJDcrpKhFSm4IarZeNf0Nzmj7fmA/5OZFbGZIRSnUntyhOHjGUGsLMulAak+bihocSs6KhoffCbdY4A1JB3TI20x9CLeueE1Iw05CwcBVuKzduWH9SkPIagB0pkAdFHRy438FZtAZbCEFFkw84dgxG6qlb5iHxl0= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1782557189; c=relaxed/simple; bh=G4J1Zudwy0O3ZqudIuL2fq7C8pSE22foO/s/bHWhN6g=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=DzKsJn8vN6RxL3HB0836vIZKaMbU3iTAwGIGHrIiZSWj9dIzzxBDih9++l/pCGbEdtRNgWoIwlS614rlvRcgbP9RoyaP7y/d4+OzoOd4KIZ97ISc/xulhiGfaoLuJsMicGWxVGA4j1iTX1NcrWBBiVtv/l0FDwNyJ9eA6ixpVZE= ARC-Authentication-Results: i=1; sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org EE35E4BA2E32 Received: from localhost.localdomain (unknown [157.0.80.168]) by APP-01 (Coremail) with SMTP id qwCowACXMcr6qT9qMtWNAw--.25411S4; Sat, 27 Jun 2026 18:46:20 +0800 (CST) From: Jiawei To: binutils@sourceware.org Cc: nelson@rivosinc.com, jbeulich@suse.com, jeremy.bennett@embecosm.com, kito.cheng@sifive.com, mary.bennett@embecosm.com, nandni.jamnadas@embecosm.com, charlie.keaney@embecosm.com, hau.hsu@sifive.com, jerry.zhangjian@sifive.com, sinan.lin@linux.alibaba.com, Jiawei Subject: [RFC PATCH 2/5] RISC-V: Add Zcmt table-jump relaxation Date: Sat, 27 Jun 2026 18:45:52 +0800 Message-ID: <20260627104555.331493-3-jiawei@iscas.ac.cn> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260627104555.331493-1-jiawei@iscas.ac.cn> References: <20260627104555.331493-1-jiawei@iscas.ac.cn> MIME-Version: 1.0 X-CM-TRANSID: qwCowACXMcr6qT9qMtWNAw--.25411S4 X-Coremail-Antispam: 1UD129KBjvAXoWDCw4kWryfXryrAF48tr47Arb_yoWrAF17Ko WrXrs5Xw4UWr17urykCF1xGa18XrW8JrWYqan8Zr4rGF4UCrW8u34Iya1rJayaqr43KFW7 C3W7Xa93JF48WFn7n29KB7ZKAUJUUUU8529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 AaLaJ3UjIYCTnIWjp_UUUOv7AC8VAFwI0_Wr0E3s1l1xkIjI8I6I8E6xAIw20EY4v20xva j40_Wr0E3s1l1IIY67AEw4v_Jr0_Jr4l82xGYIkIc2x26280x7IE14v26r15M28IrcIa0x kI8VCY1x0267AKxVW5JVCq3wA2ocxC64kIII0Yj41l84x0c7CEw4AK67xGY2AK021l84AC jcxK6xIIjxv20xvE14v26r4j6ryUM28EF7xvwVC0I7IYx2IY6xkF7I0E14v26r4j6F4UM2 8EF7xvwVC2z280aVAFwI0_GcCE3s1l84ACjcxK6I8E87Iv6xkF7I0E14v26rxl6s0DM2AI xVAIcxkEcVAq07x20xvEncxIr21l5I8CrVACY4xI64kE6c02F40Ex7xfMcIj6xIIjxv20x vE14v26r1j6r18McIj6xkF7I0En7xvr7AKxVWUJVW8JwAv7VC2z280aVAFwI0_Jr0_Gr1l Ox8S6xCaFVCjc4AY6r1j6r4UM4x0Y48IcxkI7VAKI48JM4x0x7Aq67IIx4CEVc8vx2IErc IFxwACI402YVCY1x02628vn2kIc2xKxwCY1x0262kKe7AKxVWUtVW8ZwCF04k20xvY0x0E wIxGrwCFx2IqxVCFs4IE7xkEbVWUJVW8JwC20s026c02F40E14v26r1j6r18MI8I3I0E74 80Y4vE14v26r106r1rMI8E67AF67kF1VAFwI0_Jw0_GFylIxkGc2Ij64vIr41lIxAIcVC0 I7IYx2IY67AKxVWUJVWUCwCI42IY6xIIjxv20xvEc7CjxVAFwI0_Gr0_Cr1lIxAIcVCF04 k26cxKx2IYs7xG6r1j6r1xMIIF0xvEx4A2jsIE14v26r1j6r4UMIIF0xvEx4A2jsIEc7Cj xVAFwI0_Gr0_Gr1UYxBIdaVFxhVjvjDU0xZFpf9x0JUDOz3UUUUU= X-Originating-IP: [157.0.80.168] X-CM-SenderInfo: 5mld4v3l6l2u1dvotugofq/1tbiDAELAGo-mA8f+AAAsj X-Spam-Status: No, score=-10.8 required=5.0 tests=BAYES_00, DRUGS_ERECTILE, DRUGS_ERECTILE_OBFU, GIT_PATCH_0, KAM_DMARC_STATUS, SPF_HELO_PASS, SPF_PASS shortcircuit=no autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on sourceware.org X-BeenThere: binutils@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Binutils mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: binutils-bounces~patchwork=sourceware.org@sourceware.org Collect profitable post-relax call and jump sites, rank JT and JALT candidates deterministically, emit a JVT only when the net benefit is positive, and rewrite selected sites to table-jump relocations for non-position-independent executable links. bfd/ChangeLog: * elfnn-riscv.c (struct riscv_elf_link_hash_table): Add JVT fields. (riscv_set_jvt_addr): Add Zcmt support. (riscv_is_local_symbol): Ditto. (riscv_is_special_symbol_name): Ditto. (riscv_jvt_global_hash_entry): Ditto. (riscv_jvt_init_key): Ditto. (riscv_jvt_key_hash): Ditto. (riscv_jvt_htab_hash): Ditto. (riscv_jvt_key_eq): Ditto. (riscv_jvt_htab_entry_eq): Ditto. (riscv_init_jvt_htab): Ditto. (riscv_free_jvt_htab): Ditto. (riscv_ensure_jvt_htab): Ditto. (riscv_update_jvt_entry): Ditto. (riscv_elf_link_hash_table_free): Ditto. (riscv_elf_link_hash_table_create): Ditto. (riscv_use_jvt): Ditto. (riscv_elf_create_jvt_section): Ditto. (riscv_reject_local_jvt_base_symbol): Ditto. (riscv_define_jvt_base_symbol): Ditto. (riscv_elf_check_relocs): Ditto. (perform_relocation): Ditto. (riscv_elf_relocate_section): Ditto. (riscv_get_jvt_htab): Ditto. (_bfd_riscv_jvt_record): Ditto. (riscv_compare_jvt_key): Ditto. (riscv_jvt_entry_better): Ditto. (riscv_ranking_jvt): Ditto. (riscv_record_jvt_index): Ditto. (riscv_jvt_profiling): Ditto. (_bfd_riscv_jvt_mark): Ditto. (_bfd_riscv_relax_call): Ditto. (_bfd_riscv_relax_jal): Ditto. (_bfd_riscv_get_max_alignment): Ditto. (bfd_elfNN_riscv_set_data_segment_info): Ditto. (_bfd_riscv_relax_section): Ditto. (riscv_final_link): Ditto. (bfd_elfNN_bfd_final_link): Ditto. --- bfd/elfnn-riscv.c | 1134 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 1098 insertions(+), 36 deletions(-) diff --git a/bfd/elfnn-riscv.c b/bfd/elfnn-riscv.c index 1c1c3ea36c5..b1b21e996e8 100644 --- a/bfd/elfnn-riscv.c +++ b/bfd/elfnn-riscv.c @@ -27,6 +27,7 @@ #include "libbfd.h" #include "bfdlink.h" #include "genlink.h" +#include "hashtab.h" #include "elf-bfd.h" #include "elfxx-riscv.h" #include "elf/riscv.h" @@ -203,6 +204,65 @@ elfNN_riscv_mkobject (bfd *abfd) #include "elf/common.h" #include "elf/internal.h" +/* Identity of one JVT entry. */ +/* JVT candidates are keyed by relocation symbol identity plus addend and PLT + selection. This v2 implementation deliberately does not canonicalize + aliases to final section+offset addresses after ordinary relaxation. */ +typedef struct +{ + bool is_local; + bool use_plt; + bfd *input_bfd; + unsigned long symndx; + struct elf_link_hash_entry *h; + bfd_signed_vma addend; +} riscv_jvt_key_t; + +/* Per-slot data for JVT entries. */ +typedef struct +{ + bfd_size_type benefit; + bfd_size_type first_seen; + riscv_jvt_key_t key; + const char *name; +} riscv_jvt_slot_t; + +/* Hash table for storing table jump candidate entries. */ +typedef struct +{ + /* Hash tables for cm.jt and cm.jalt. They record all possible + entries and will be ranked to put the most beneficial ones into JVT + section. */ + htab_t jt_htab; + htab_t jalt_htab; + + /* Target-endian contents that will be put into JVT section. */ + bfd_byte *jvt_addrs; + + asection *jvt_sec; + bfd *jvt_sec_owner; + + /* END_IDX is used to calculate size of used slots in the table jump section, + and it is set to -1 if the profiling stage is complete. */ + int end_idx; + bfd_size_type total_benefits; + bfd_size_type next_ordinal; + + /* Unified slot array for ranked JVT entries. */ + riscv_jvt_slot_t *slots; +} riscv_jvt_htab_t; + +typedef struct +{ + unsigned int index; + + riscv_jvt_key_t key; + + bfd_size_type benefit; + bfd_size_type first_seen; + const char *name; +} riscv_jvt_htab_entry; + struct riscv_elf_link_hash_table { struct elf_link_hash_table elf; @@ -241,6 +301,11 @@ struct riscv_elf_link_hash_table bool (*make_plt_header) (bfd *output_bfd, struct riscv_elf_link_hash_table *htab); bool (*make_plt_entry) (bfd *output_bfd, asection *got, bfd_vma got_offset, asection *plt, bfd_vma plt_offset); + + riscv_jvt_htab_t *jvt_htab; + + /* Cached result for riscv_use_jvt, scoped to one link. */ + int use_jvt; }; /* Instruction access functions. */ @@ -266,6 +331,8 @@ static bool riscv_make_plt_header (bfd *, struct riscv_elf_link_hash_table *); static bool riscv_make_plt_entry (bfd *, asection *, bfd_vma, asection *, bfd_vma); +static void +riscv_set_jvt_addr (struct bfd_link_info *, unsigned int, bfd_vma); void riscv_elfNN_set_options (struct bfd_link_info *link_info, @@ -307,6 +374,13 @@ riscv_is_insn_reloc (const reloc_howto_type *howto) ? (MINUS_ONE << howto->bitsize) : (bfd_vma)0)) != 0); } +/* Return true if the given symbol index is a local symbol. */ +static inline bool +riscv_is_local_symbol (Elf_Internal_Shdr *symtab_hdr, unsigned long symndx) +{ + return symndx < symtab_hdr->sh_info; +} + /* PLT/GOT stuff. */ #define PLT_HEADER_INSNS 8 #define PLT_ENTRY_INSNS 4 @@ -533,6 +607,14 @@ riscv_make_plt_zicfilp_unlabeled_entry (bfd *output_bfd, asection *got, return true; } +static inline bool +riscv_is_special_symbol_name (bfd *abfd, const char *name) +{ + return (!strcmp (name, "") + || _bfd_elf_is_local_label_name (abfd, name) + || riscv_elf_is_mapping_symbols (name)); +} + /* Create an entry in an RISC-V ELF linker hash table. */ static struct bfd_hash_entry * @@ -563,6 +645,211 @@ link_hash_newfunc (struct bfd_hash_entry *entry, return entry; } +static struct elf_link_hash_entry * +riscv_jvt_global_hash_entry (bfd *abfd, unsigned long symndx) +{ + Elf_Internal_Shdr *symtab_hdr = &elf_symtab_hdr (abfd); + struct elf_link_hash_entry *h; + + if (symndx < symtab_hdr->sh_info) + return NULL; + + h = elf_sym_hashes (abfd)[symndx - symtab_hdr->sh_info]; + if (h == NULL) + return NULL; + + while (h->root.type == bfd_link_hash_indirect + || h->root.type == bfd_link_hash_warning) + h = (struct elf_link_hash_entry *) h->root.u.i.link; + + return h; +} + +static bool +riscv_jvt_init_key (struct bfd_link_info *info, bfd *abfd, + const Elf_Internal_Rela *rel, riscv_jvt_key_t *key, + const char **name) +{ + Elf_Internal_Shdr *symtab_hdr = &elf_symtab_hdr (abfd); + unsigned long symndx = ELFNN_R_SYM (rel->r_info); + + memset (key, 0, sizeof (*key)); + key->input_bfd = abfd; + key->symndx = symndx; + key->addend = rel->r_addend; + + if (riscv_is_local_symbol (symtab_hdr, symndx)) + { + Elf_Internal_Sym *sym; + + if (symtab_hdr->contents == NULL) + return false; + + sym = (Elf_Internal_Sym *) symtab_hdr->contents + symndx; + *name = bfd_elf_sym_name (abfd, symtab_hdr, sym, NULL); + key->is_local = true; + } + else + { + struct riscv_elf_link_hash_table *htab = riscv_elf_hash_table (info); + struct elf_link_hash_entry *h = riscv_jvt_global_hash_entry (abfd, + symndx); + + if (h == NULL || h->type == STT_GNU_IFUNC) + return false; + + key->h = h; + key->use_plt = htab->elf.splt != NULL && h->plt.offset != MINUS_ONE; + *name = h->root.root.string; + } + + return *name != NULL && !riscv_is_special_symbol_name (abfd, *name); +} + +static hashval_t +riscv_jvt_key_hash (const riscv_jvt_key_t *key) +{ + hashval_t h; + bfd_vma addend = (bfd_vma) key->addend; + + if (key->is_local) + { + unsigned int id = key->input_bfd->id; + unsigned int symndx = key->symndx; + + h = (id + symndx) * (id + symndx + 1) / 2 + id; + } + else + h = htab_hash_pointer (key->h); + + h ^= (hashval_t) addend; + h ^= (hashval_t) (addend >> 32); + if (key->use_plt) + h ^= 0x9e3779b9; + return h; +} + +static hashval_t +riscv_jvt_htab_hash (const void *entry) +{ + const riscv_jvt_htab_entry *e = entry; + return riscv_jvt_key_hash (&e->key); +} + +static bool +riscv_jvt_key_eq (const riscv_jvt_key_t *key1, const riscv_jvt_key_t *key2) +{ + if (key1->is_local != key2->is_local + || key1->use_plt != key2->use_plt + || key1->addend != key2->addend) + return false; + + if (key1->is_local) + return (key1->input_bfd->id == key2->input_bfd->id + && key1->symndx == key2->symndx); + + return key1->h == key2->h; +} + +static int +riscv_jvt_htab_entry_eq (const void *entry1, const void *entry2) +{ + const riscv_jvt_htab_entry *e1 = entry1, *e2 = entry2; + return riscv_jvt_key_eq (&e1->key, &e2->key); +} + +static bool +riscv_init_jvt_htab (riscv_jvt_htab_t *htab) +{ + htab->slots = bfd_zmalloc (sizeof (riscv_jvt_slot_t) * ZCMT_TOTAL_ENTRIES); + htab->jvt_addrs = bfd_zmalloc (RISCV_ELF_WORD_BYTES * ZCMT_TOTAL_ENTRIES); + if (htab->slots == NULL || htab->jvt_addrs == NULL) + return false; + htab->end_idx = 0; + htab->total_benefits = 0; + htab->next_ordinal = 0; + + htab->jt_htab = htab_create (ZCMT_JT_NUM_ENTRIES, riscv_jvt_htab_hash, + riscv_jvt_htab_entry_eq, free); + if (htab->jt_htab == NULL) + return false; + + htab->jalt_htab = htab_create (ZCMT_JALT_NUM_ENTRIES, riscv_jvt_htab_hash, + riscv_jvt_htab_entry_eq, free); + return htab->jalt_htab != NULL; +} + +static void +riscv_free_jvt_htab (riscv_jvt_htab_t *htab) +{ + free (htab->slots); + free (htab->jvt_addrs); + if (htab->jt_htab) + htab_delete (htab->jt_htab); + if (htab->jalt_htab) + htab_delete (htab->jalt_htab); +} + +static bool +riscv_ensure_jvt_htab (struct riscv_elf_link_hash_table *htab) +{ + if (htab->jvt_htab != NULL) + return true; + + htab->jvt_htab = (riscv_jvt_htab_t *) bfd_zmalloc (sizeof (*htab->jvt_htab)); + if (htab->jvt_htab == NULL) + return false; + + if (!riscv_init_jvt_htab (htab->jvt_htab)) + { + riscv_free_jvt_htab (htab->jvt_htab); + free (htab->jvt_htab); + htab->jvt_htab = NULL; + return false; + } + + return true; +} + +/* Update table jump hash entry. */ + +static bool +riscv_update_jvt_entry (riscv_jvt_htab_t *jvt_htab, htab_t htab, + const riscv_jvt_key_t *key, + bfd_size_type benefit, const char *name) +{ + riscv_jvt_htab_entry search = {.index = 0, + .key = *key, + .benefit = 0, + .first_seen = 0, + .name = NULL}; + + riscv_jvt_htab_entry *entry = htab_find (htab, &search); + + if (entry == NULL) + { + riscv_jvt_htab_entry **slot + = (riscv_jvt_htab_entry **) htab_find_slot (htab, &search, INSERT); + + BFD_ASSERT (*slot == NULL); + + *slot + = (riscv_jvt_htab_entry *) bfd_zmalloc (sizeof (riscv_jvt_htab_entry)); + + if (*slot == NULL) + return false; + + (*slot)->key = *key; + (*slot)->benefit = benefit; + (*slot)->first_seen = jvt_htab->next_ordinal++; + (*slot)->name = name; + } + else + entry->benefit += benefit; + + return true; +} + /* Compute a hash of a local hash entry. We use elf_link_hash_entry for local symbol so that we can handle local STT_GNU_IFUNC symbols as global symbol. We reuse indx and dynstr_index for local symbol @@ -640,6 +927,12 @@ riscv_elf_link_hash_table_free (bfd *obfd) if (ret->loc_hash_memory) objalloc_free ((struct objalloc *) ret->loc_hash_memory); + if (ret->jvt_htab) + { + riscv_free_jvt_htab (ret->jvt_htab); + free (ret->jvt_htab); + } + _bfd_elf_link_hash_table_free (obfd); } @@ -696,6 +989,7 @@ riscv_elf_link_hash_table_create (bfd *abfd) ret->max_alignment = (bfd_vma) -1; ret->max_alignment_for_gp = (bfd_vma) -1; + ret->use_jvt = -1; setup_plt_values (abfd, ret, PLT_NORMAL); @@ -915,6 +1209,193 @@ bad_static_reloc (bfd *abfd, unsigned r_type, struct elf_link_hash_entry *h) return false; } +static bool +riscv_use_jvt (struct bfd_link_info *info) +{ + unsigned xlen = ARCH_SIZE; + riscv_subset_list_t subsets; + struct riscv_elf_link_hash_table *htab; + + htab = riscv_elf_hash_table (info); + if (htab->use_jvt >= 0) + return htab->use_jvt; + + /* If relax is disabled by user, generating position-independent output, + or not linking an executable, table jump insns will not be generated. */ + if (info->disable_target_specific_optimizations >= 1 + || bfd_link_pic (info) + || !bfd_link_executable (info) + || !htab->params->relax_zcmt) + { + htab->use_jvt = 0; + return htab->use_jvt; + } + + bfd *obfd = info->output_bfd; + obj_attribute *out_attr = elf_known_obj_attributes_proc (obfd); + + subsets.head = NULL; + subsets.tail = NULL; + subsets.arch_str = NULL; + + riscv_parse_subset_t riscv_rps_ld_out + = {&subsets, _bfd_error_handler, &xlen, NULL, false}; + + if (!riscv_parse_subset (&riscv_rps_ld_out, out_attr[Tag_RISCV_arch].s)) + { + htab->use_jvt = 0; + riscv_release_subset_list (&subsets); + return htab->use_jvt; + } + + /* Mirror the ISA and psABI constraints: Zcmt depends on Zca and Zicsr, + and its encodings overlap with Zcd compressed floating-point encodings. */ + htab->use_jvt = (riscv_subset_supports (&riscv_rps_ld_out, "zcmt") + && riscv_subset_supports (&riscv_rps_ld_out, "zca") + && riscv_subset_supports (&riscv_rps_ld_out, "zicsr") + && !riscv_subset_supports (&riscv_rps_ld_out, "zcd")); + riscv_release_subset_list (&subsets); + + return htab->use_jvt; +} + +static bool +riscv_elf_create_jvt_section (bfd *abfd, struct bfd_link_info *info) +{ + asection *sec; + struct riscv_elf_link_hash_table *htab; + + /* Skip if no Zcmt. */ + if (!riscv_use_jvt (info)) + return true; + + htab = riscv_elf_hash_table (info); + if (!riscv_ensure_jvt_htab (htab)) + return false; + sec = bfd_get_linker_section (abfd, TABLE_JUMP_SEC_NAME); + + if (sec != NULL) + return true; + + if (htab->jvt_htab->jvt_sec == NULL) + { + sec = bfd_make_section_anyway_with_flags ( + abfd, TABLE_JUMP_SEC_NAME, + (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_HAS_CONTENTS | SEC_IN_MEMORY + | SEC_KEEP | SEC_CODE)); + + /* Create only a zero-sized placeholder before relaxation. The Zcmt + profiling pass sets the final alignment and size if a profitable + table is chosen, so links that opt in but select no JVT do not reserve + a full table or perturb layout. */ + if (sec == NULL || !bfd_set_section_alignment (sec, 0) + || !bfd_set_section_size (sec, 0)) + return false; + + htab->jvt_htab->jvt_sec = sec; + htab->jvt_htab->jvt_sec_owner = abfd; + } + + return true; +} + +static bool +riscv_reject_local_jvt_base_symbol (bfd *abfd) +{ + Elf_Internal_Shdr *symtab_hdr = &elf_symtab_hdr (abfd); + Elf_Internal_Sym *isymbuf; + unsigned long symndx; + + if (symtab_hdr->sh_info == 0) + return true; + + if (symtab_hdr->contents == NULL + && !(symtab_hdr->contents = (unsigned char *) bfd_elf_get_elf_syms + (abfd, symtab_hdr, symtab_hdr->sh_info, 0, NULL, NULL, NULL))) + return false; + + isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents; + for (symndx = 0; symndx < symtab_hdr->sh_info; symndx++) + { + const char *name = bfd_elf_sym_name (abfd, symtab_hdr, + isymbuf + symndx, NULL); + + if (name != NULL && strcmp (name, RISCV_TABLE_JUMP_BASE_SYMBOL) == 0) + { + _bfd_error_handler + (_("%pB: %s is reserved for Zcmt table-jump relaxation"), + abfd, RISCV_TABLE_JUMP_BASE_SYMBOL); + bfd_set_error (bfd_error_bad_value); + return false; + } + } + + return true; +} + +static bool +riscv_define_jvt_base_symbol (bfd *abfd, struct bfd_link_info *info) +{ + struct riscv_elf_link_hash_table *htab = riscv_elf_hash_table (info); + riscv_jvt_htab_t *jvt_htab = htab->jvt_htab; + struct elf_link_hash_entry *h; + struct bfd_link_hash_entry *bh = NULL; + const struct elf_backend_data *bed = get_elf_backend_data (abfd); + bfd *ibfd; + + if (jvt_htab == NULL || jvt_htab->jvt_sec == NULL + || jvt_htab->jvt_sec->size == 0) + return true; + + if (jvt_htab->jvt_sec->contents == NULL) + { + jvt_htab->jvt_sec->contents + = (bfd_byte *) bfd_zalloc (jvt_htab->jvt_sec->owner, + jvt_htab->jvt_sec->size); + jvt_htab->jvt_sec->alloced = 1; + if (jvt_htab->jvt_sec->contents == NULL) + return false; + } + + h = elf_link_hash_lookup (elf_hash_table (info), + RISCV_TABLE_JUMP_BASE_SYMBOL, + false, false, true); + /* Code may reference __jvt_base$ to initialize the JVT CSR before + executing cm.jt/cm.jalt. That is not a user definition; resolve + undefined references by defining the linker-owned symbol below, but + still reject any user-provided definition of the reserved name. */ + if (h != NULL + && h->root.type != bfd_link_hash_new + && h->root.type != bfd_link_hash_undefined + && h->root.type != bfd_link_hash_undefweak) + { + _bfd_error_handler + (_("%pB: %s is reserved for Zcmt table-jump relaxation"), + abfd, RISCV_TABLE_JUMP_BASE_SYMBOL); + bfd_set_error (bfd_error_bad_value); + return false; + } + + for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next) + if (!riscv_reject_local_jvt_base_symbol (ibfd)) + return false; + + if (!_bfd_generic_link_add_one_symbol (info, abfd, + RISCV_TABLE_JUMP_BASE_SYMBOL, + BSF_GLOBAL, jvt_htab->jvt_sec, + 0, NULL, true, bed->collect, &bh)) + return false; + + h = (struct elf_link_hash_entry *) bh; + h->root.linker_def = 1; + h->def_regular = 1; + h->type = STT_NOTYPE; + if (ELF_ST_VISIBILITY (h->other) != STV_INTERNAL) + h->other = ((h->other & ~ELF_ST_VISIBILITY (-1)) | STV_HIDDEN); + bed->elf_backend_hide_symbol (info, h, true); + return true; +} + /* Look through the relocs for a section during the first phase, and allocate space in the global offset table or procedure linkage table. */ @@ -1261,6 +1742,9 @@ riscv_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, } } + if (!riscv_elf_create_jvt_section (abfd, info)) + return false; + return true; } @@ -2037,6 +2521,9 @@ perform_relocation (const reloc_howto_type *howto, value = ENCODE_CBTYPE_IMM (value); break; + case R_RISCV_TABLE_JUMP: + return bfd_reloc_ok; + case R_RISCV_RVC_JUMP: if (!VALID_CJTYPE_IMM (value)) return bfd_reloc_overflow; @@ -2985,6 +3472,24 @@ riscv_elf_relocate_section (struct bfd_link_info *info, } break; + case R_RISCV_TABLE_JUMP: + { + bfd_vma insn = bfd_getl16 (contents + rel->r_offset); + unsigned int tbl_index = EXTRACT_ZCMT_INDEX (insn); + + if (via_plt) + { + relocation = sec_addr (htab->elf.splt) + h->plt.offset; + unresolved_reloc = false; + } + + if (!riscv_ensure_jvt_htab (htab)) + return false; + riscv_set_jvt_addr (info, tbl_index, relocation + rel->r_addend); + rel->r_info = ELFNN_R_INFO (0, R_RISCV_NONE); + continue; + } + case R_RISCV_CALL: case R_RISCV_CALL_PLT: /* Handle a call to an undefined weak function. This won't be @@ -4267,6 +4772,331 @@ _riscv_relax_delete_immediate (bfd *abfd, link_info, p, 0, sec->size); } +/* Return the cm.jt hash table for x0, or the cm.jalt hash table for ra. */ + +static htab_t +riscv_get_jvt_htab (struct bfd_link_info *info, unsigned int link_reg) +{ + struct riscv_elf_link_hash_table *htab = riscv_elf_hash_table (info); + + if (htab == NULL || !riscv_ensure_jvt_htab (htab)) + return NULL; + + if (link_reg == 0) + return htab->jvt_htab->jt_htab; + if (link_reg == X_RA) + return htab->jvt_htab->jalt_htab; + + return NULL; +} + +/* Record JAL, CALL, or CALL_PLT as a jump table candidate. */ + +static bool +_bfd_riscv_jvt_record (bfd *abfd, asection *sec ATTRIBUTE_UNUSED, + asection *sym_sec ATTRIBUTE_UNUSED, + struct bfd_link_info *link_info, Elf_Internal_Rela *rel, + bfd_vma symval ATTRIBUTE_UNUSED, + bfd_vma max_alignment ATTRIBUTE_UNUSED, + bfd_vma reserve_size ATTRIBUTE_UNUSED, + bool *again ATTRIBUTE_UNUSED, + riscv_pcgp_relocs *pcgp_relocs ATTRIBUTE_UNUSED, + bool undefined_weak ATTRIBUTE_UNUSED) +{ + bfd_byte *contents = elf_section_data (sec)->this_hdr.contents; + int type = ELFNN_R_TYPE (rel->r_info); + bfd_vma insn; + bfd_size_type benefit; + unsigned int rd; + htab_t tbljal_htab; + const char *name; + riscv_jvt_key_t key; + + if (type == R_RISCV_CALL || type == R_RISCV_CALL_PLT) + { + insn = bfd_getl32 (contents + rel->r_offset + 4); + benefit = (4 + 4) - 2; /* AUIPC + JALR -> cm.jt/cm.jalt. */ + } + else if (type == R_RISCV_JAL) + { + insn = bfd_getl32 (contents + rel->r_offset); + benefit = 4 - 2; /* JAL -> cm.jt/cm.jalt. */ + } + else + { + BFD_ASSERT (false); + return true; + } + + rd = (insn >> OP_SH_RD) & OP_MASK_RD; + tbljal_htab = riscv_get_jvt_htab (link_info, rd); + + if (tbljal_htab == NULL) + return true; + + if (!riscv_jvt_init_key (link_info, abfd, rel, &key, &name)) + return true; + + return riscv_update_jvt_entry (riscv_elf_hash_table (link_info)->jvt_htab, + tbljal_htab, &key, benefit, name); +} + +static void +riscv_set_jvt_addr (struct bfd_link_info *info, unsigned int index, + bfd_vma addr) +{ + struct riscv_elf_link_hash_table *htab = riscv_elf_hash_table (info); + bfd_byte *loc; + + BFD_ASSERT (index < ZCMT_TOTAL_ENTRIES); + BFD_ASSERT (htab->jvt_htab != NULL); + + addr &= ~(bfd_vma) 1; + loc = htab->jvt_htab->jvt_addrs + index * RISCV_ELF_WORD_BYTES; + bfd_put_NN (info->output_bfd, addr, loc); +} + +typedef struct +{ + riscv_jvt_htab_t *htab; + unsigned int start; + unsigned int end; +} riscv_jvt_args; + +static int +riscv_compare_jvt_key (const riscv_jvt_key_t *key1, const char *name1, + const riscv_jvt_key_t *key2, const char *name2) +{ + int cmp; + + cmp = strcmp (name1 == NULL ? "" : name1, name2 == NULL ? "" : name2); + if (cmp != 0) + return cmp; + + cmp = strcmp (bfd_get_filename (key1->input_bfd), + bfd_get_filename (key2->input_bfd)); + if (cmp != 0) + return cmp; + + if (key1->symndx != key2->symndx) + return key1->symndx < key2->symndx ? -1 : 1; + if (key1->addend != key2->addend) + return key1->addend < key2->addend ? -1 : 1; + if (key1->use_plt != key2->use_plt) + return key1->use_plt ? 1 : -1; + return 0; +} + +static bool +riscv_jvt_entry_better (const riscv_jvt_htab_entry *entry, + const riscv_jvt_slot_t *slot) +{ + if (slot->benefit == 0) + return true; + if (entry->benefit != slot->benefit) + return entry->benefit > slot->benefit; + if (entry->first_seen != slot->first_seen) + return entry->first_seen < slot->first_seen; + return riscv_compare_jvt_key (&entry->key, entry->name, &slot->key, + slot->name) < 0; +} + +static int +riscv_ranking_jvt (void **entry_ptr, void *arg_) +{ + const riscv_jvt_htab_entry *entry = *entry_ptr; + riscv_jvt_args *arg = arg_; + riscv_jvt_slot_t *slots = arg->htab->slots; + unsigned int left; + + for (left = arg->start; left <= arg->end; left++) + if (riscv_jvt_entry_better (entry, &slots[left])) + break; + + if (left > arg->end) + return true; + + for (unsigned int idx = arg->end; idx > left; idx--) + slots[idx] = slots[idx - 1]; + + slots[left].benefit = entry->benefit; + slots[left].first_seen = entry->first_seen; + slots[left].name = entry->name; + slots[left].key = entry->key; + + return true; +} + +static bool +riscv_record_jvt_index (htab_t htab, riscv_jvt_args *args, + unsigned int count) +{ + riscv_jvt_htab_t *jvt_htab = args->htab; + riscv_jvt_slot_t *slots = jvt_htab->slots; + riscv_jvt_htab_entry *entry = NULL; + unsigned int idx, end; + + end = args->start + count; + for (idx = args->start; idx < end; idx++) + { + riscv_jvt_htab_entry search = + { + .index = 0, + .key = slots[idx].key, + .benefit = 0, + .first_seen = 0, + .name = NULL, + }; + + entry = htab_find (htab, &search); + + BFD_ASSERT (entry != NULL); + entry->index = idx + 1; + jvt_htab->total_benefits += slots[idx].benefit; + } + + if (entry != NULL && entry->index != 0) + jvt_htab->end_idx = entry->index; + + return true; +} + +static bool +riscv_jvt_profiling (riscv_jvt_htab_t *jvt_htab, riscv_jvt_args *args) +{ + bfd_size_type jt_prefix[ZCMT_JT_NUM_ENTRIES + 1]; + bfd_size_type jalt_prefix[ZCMT_JALT_NUM_ENTRIES + 1]; + unsigned int jt_count = 0; + unsigned int jalt_count = 0; + unsigned int best_jt = 0; + unsigned int best_jalt = 0; + unsigned int best_entries = 0; + bfd_size_type best_benefit = 0; + bfd_size_type best_net = 0; + + memset (jvt_htab->slots, 0, + sizeof (riscv_jvt_slot_t) * ZCMT_TOTAL_ENTRIES); + jvt_htab->total_benefits = 0; + jvt_htab->end_idx = 0; + + args->start = ZCMT_JT_BEGIN; + args->end = ZCMT_JT_END; + htab_traverse (jvt_htab->jt_htab, riscv_ranking_jvt, args); + + args->start = ZCMT_JALT_BEGIN; + args->end = ZCMT_JALT_END; + htab_traverse (jvt_htab->jalt_htab, riscv_ranking_jvt, args); + + jt_prefix[0] = 0; + while (jt_count < ZCMT_JT_NUM_ENTRIES + && jvt_htab->slots[ZCMT_JT_BEGIN + jt_count].benefit != 0) + { + jt_prefix[jt_count + 1] + = jt_prefix[jt_count] + + jvt_htab->slots[ZCMT_JT_BEGIN + jt_count].benefit; + jt_count++; + } + + jalt_prefix[0] = 0; + while (jalt_count < ZCMT_JALT_NUM_ENTRIES + && jvt_htab->slots[ZCMT_JALT_BEGIN + jalt_count].benefit != 0) + { + jalt_prefix[jalt_count + 1] + = jalt_prefix[jalt_count] + + jvt_htab->slots[ZCMT_JALT_BEGIN + jalt_count].benefit; + jalt_count++; + } + + for (unsigned int jt = 0; jt <= jt_count; jt++) + for (unsigned int jalt = 0; jalt <= jalt_count; jalt++) + { + unsigned int entries; + bfd_size_type benefit; + bfd_size_type table_cost, net; + + if (jt == 0 && jalt == 0) + entries = 0; + else if (jalt == 0) + entries = jt; + else + entries = ZCMT_JALT_BEGIN + jalt; + + benefit = jt_prefix[jt] + jalt_prefix[jalt]; + table_cost = (bfd_size_type) entries * RISCV_ELF_WORD_BYTES; + net = benefit > table_cost ? benefit - table_cost : 0; + + if (net > best_net + || (net == best_net + && (entries < best_entries + || (entries == best_entries + && benefit > best_benefit)))) + { + best_net = net; + best_jt = jt; + best_jalt = jalt; + best_entries = entries; + best_benefit = benefit; + } + } + + if (best_net == 0) + { + if (jvt_htab->jvt_sec != NULL) + { + asection *sec = jvt_htab->jvt_sec; + asection *out_sec = sec->output_section; + + /* The JVT placeholder is created before profitability is known so + that orphan placement and relaxation sizing can see a normal + linker-created section. When no positive-benefit table is chosen, + SEC_EXCLUDE alone is not enough: the orphan output section may + already have been inserted into the output BFD section list and a + zero-sized .riscv.jvt would remain visible to later layout and + inspection. It is safe to remove these sections here because this + path runs before __jvt_base$ is defined, the placeholder has no + user input section owner, and no table-jump relocations have been + marked. Tests cover both custom-script and default-script no-JVT + outputs. */ + sec->flags &= ~SEC_KEEP; + sec->flags |= SEC_EXCLUDE; + sec->output_section = bfd_abs_section_ptr; + + if (out_sec != NULL && out_sec != bfd_abs_section_ptr) + { + out_sec->flags &= ~SEC_KEEP; + out_sec->flags |= SEC_EXCLUDE; + if (!bfd_section_removed_from_list (out_sec->owner, out_sec)) + { + bfd_section_list_remove (out_sec->owner, out_sec); + out_sec->owner->section_count--; + } + } + + if (sec != out_sec + && !bfd_section_removed_from_list (sec->owner, sec)) + { + bfd_section_list_remove (sec->owner, sec); + sec->owner->section_count--; + } + } + jvt_htab->end_idx = -1; + return true; + } + + args->start = ZCMT_JT_BEGIN; + args->end = ZCMT_JT_END; + riscv_record_jvt_index (jvt_htab->jt_htab, args, best_jt); + + args->start = ZCMT_JALT_BEGIN; + args->end = ZCMT_JALT_END; + riscv_record_jvt_index (jvt_htab->jalt_htab, args, best_jalt); + + jvt_htab->end_idx = best_entries; + jvt_htab->total_benefits = best_benefit; + + return true; +} + /* Return true if TYPE is a delete relocation. */ static bool @@ -4346,7 +5176,84 @@ typedef bool (*relax_func_t) (bfd *, asection *, asection *, riscv_pcgp_relocs *, bool undefined_weak); -/* Relax AUIPC + JALR into JAL. */ +/* Mark JAL/CALL/CALL_PLT to use table jump instructions. */ + +static bool +_bfd_riscv_jvt_mark (bfd *abfd, asection *sec, + asection *sym_sec ATTRIBUTE_UNUSED, + struct bfd_link_info *link_info, Elf_Internal_Rela *rel, + bfd_vma symval ATTRIBUTE_UNUSED, + bfd_vma max_alignment ATTRIBUTE_UNUSED, + bfd_vma reserve_size ATTRIBUTE_UNUSED, + bool *again, + riscv_pcgp_relocs *pcgp_relocs, + bool undefined_weak ATTRIBUTE_UNUSED) +{ + bfd_byte *contents = elf_section_data (sec)->this_hdr.contents; + int type = ELFNN_R_TYPE (rel->r_info); + bfd_byte *jump_inst_location = NULL; + bfd_vma target, jump_inst; + unsigned int rd; + htab_t tbljal_htab; + riscv_jvt_key_t key; + const char *name; + riscv_jvt_htab_entry search; + riscv_jvt_htab_entry *entry; + size_t delete_count = 0; + + if (type == R_RISCV_JAL) + { + jump_inst_location = contents + rel->r_offset; + delete_count = 2; + } + else if (type == R_RISCV_CALL || type == R_RISCV_CALL_PLT) + { + jump_inst_location = contents + rel->r_offset + 4; + delete_count = 6; + } + else + { + /* Dispatch should only pass JAL/CALL/CALL_PLT here. Keep malformed + or unexpected input from turning an internal invariant into a crash. */ + BFD_ASSERT (false); + return true; + } + + jump_inst = bfd_getl32 (jump_inst_location); + rd = (jump_inst >> OP_SH_RD) & OP_MASK_RD; + tbljal_htab = riscv_get_jvt_htab (link_info, rd); + + /* Check if it uses a valid link register. */ + if (tbljal_htab == NULL) + return true; + + if (!riscv_jvt_init_key (link_info, abfd, rel, &key, &name)) + return true; + + search.index = 0; + search.key = key; + search.benefit = 0; + search.first_seen = 0; + search.name = NULL; + entry = htab_find (tbljal_htab, &search); + + /* entry->index == 0 when the entry is not used as a table jump entry. */ + if (entry != NULL && entry->index > 0) + { + target = MATCH_CM_JT | ENCODE_ZCMT_INDEX (entry->index - 1); + bfd_putl16 (target, contents + rel->r_offset); + rel->r_info + = ELFNN_R_INFO (ELFNN_R_SYM (rel->r_info), R_RISCV_TABLE_JUMP); + *again = true; + return riscv_relax_delete_bytes (abfd, sec, rel->r_offset + 2, + delete_count, link_info, pcgp_relocs, + rel + 1, false); + } + + return true; +} + +/* Relax AUIPC + JALR into JAL or CM.[JT,JALT]. */ static bool _bfd_riscv_relax_call (bfd *abfd, asection *sec, asection *sym_sec, @@ -4365,6 +5272,9 @@ _bfd_riscv_relax_call (bfd *abfd, asection *sec, asection *sym_sec, bfd_vma auipc, jalr; int rd, r_type, len = 4, rvc = elf_elfheader (abfd)->e_flags & EF_RISCV_RVC; + auipc = bfd_getl32 (contents + rel->r_offset); + jalr = bfd_getl32 (contents + rel->r_offset + 4); + /* If the call crosses section boundaries, an alignment directive could cause the PC-relative offset to later increase, so we need to add in the max alignment of any section inclusive from the call to the target. @@ -4384,8 +5294,6 @@ _bfd_riscv_relax_call (bfd *abfd, asection *sec, asection *sym_sec, /* Shorten the function call. */ BFD_ASSERT (rel->r_offset + 8 <= sec->size); - auipc = bfd_getl32 (contents + rel->r_offset); - jalr = bfd_getl32 (contents + rel->r_offset + 4); rd = (jalr >> OP_SH_RD) & OP_MASK_RD; rvc = rvc && VALID_CJTYPE_IMM (foff); @@ -4442,13 +5350,14 @@ _bfd_riscv_relax_jal (bfd *abfd, asection *sec, asection *sym_sec, bfd_byte *contents = elf_section_data (sec)->this_hdr.contents; bfd_vma foff = symval - (sec_addr (sec) + rel->r_offset); bool rvc = elf_elfheader (abfd)->e_flags & EF_RISCV_RVC; + bfd_vma jal = bfd_getl32 (contents + rel->r_offset); + int rd; /* Can't relax to compressed instruction without RVC. */ if (!rvc) return true; - bfd_vma jal = bfd_getl32 (contents + rel->r_offset); - int rd = (jal >> OP_SH_RD) & OP_MASK_RD; + rd = (jal >> OP_SH_RD) & OP_MASK_RD; /* C.J exists on RV32 and RV64, but C.JAL is RV32-only. */ if (!(rd == 0 || (rd == X_RA && ARCH_SIZE == 32))) @@ -4503,6 +5412,11 @@ _bfd_riscv_get_max_alignment (asection *sec, bfd_vma gp) for (o = sec->output_section->owner->sections; o != NULL; o = o->next) { bool valid = true; + /* Exclude the table jump section because it does not affect + alignment. */ + if (strcmp (o->name, TABLE_JUMP_SEC_NAME) == 0) + continue; + if (gp && !(VALID_ITYPE_IMM (sec_addr (o) - gp) || VALID_ITYPE_IMM (sec_addr (o) + o->size - gp))) @@ -4909,10 +5823,10 @@ bfd_elfNN_riscv_set_data_segment_info (struct bfd_link_info *info, } /* Relax a section. - Pass 0: Shortens code sequences for LUI/CALL/TPREL/PCREL relocs and deletes the obsolete bytes. - Pass 1: Which cannot be disabled, handles code alignment directives. */ + Pass 1: Table jump profiling. + Pass 2: Which cannot be disabled, handles code alignment directives. */ static bool _bfd_riscv_relax_section (bfd *abfd, asection *sec, @@ -4925,19 +5839,17 @@ _bfd_riscv_relax_section (bfd *abfd, asection *sec, Elf_Internal_Rela *relocs; bool ret = false; unsigned int i; - bfd_vma max_alignment, reserve_size = 0; + bfd_vma max_alignment, reserve_size = 0, used_bytes, trimmed_bytes; riscv_pcgp_relocs pcgp_relocs; static asection *first_section = NULL; + riscv_jvt_htab_t *jvt_htab = NULL; *again = false; - if (bfd_link_relocatable (info) - || sec->sec_flg0 - || sec->reloc_count == 0 - || (sec->flags & SEC_RELOC) == 0 - || (sec->flags & SEC_HAS_CONTENTS) == 0 + if (bfd_link_relocatable (info) || sec->sec_flg0 || sec->reloc_count == 0 + || (sec->flags & SEC_RELOC) == 0 || (sec->flags & SEC_HAS_CONTENTS) == 0 || (info->disable_target_specific_optimizations - && info->relax_pass == 0) + && info->relax_pass <= RELAX_PASS_CAN_BE_DISABLED) /* The exp_seg_relro_adjust is enum phase_enum (0x4), and defined in ld/ldexp.h. */ || *(htab->data_segment_phase) == 4) @@ -4958,6 +5870,16 @@ _bfd_riscv_relax_section (bfd *abfd, asection *sec, else if (!(relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL, info->keep_memory))) goto fail; + /* Read this BFD's contents if we haven't done so already. */ + if (!data->this_hdr.contents + && !bfd_malloc_and_get_section (abfd, sec, &data->this_hdr.contents)) + goto fail; + + /* Read this BFD's symbols if we haven't done so already. */ + if (symtab_hdr->sh_info != 0 && !symtab_hdr->contents + && !(symtab_hdr->contents = (unsigned char *) bfd_elf_get_elf_syms ( + abfd, symtab_hdr, symtab_hdr->sh_info, 0, NULL, NULL, NULL))) + goto fail; /* Estimate the maximum alignment for all output sections once time should be enough. */ @@ -4968,6 +5890,96 @@ _bfd_riscv_relax_section (bfd *abfd, asection *sec, htab->max_alignment = max_alignment; } + /* relax_trip 0 / JVT_PROFILING_RECORD_SYM: + Record symbol address and expected size saving of each relocation + that can be replaced by table jump instructions. + + relax_trip 1 / JVT_PROFILING_RANK: + Rank the best ZCMT_JT_NUM_ENTRIES relocations to replace for cm.jt and + the best ZCMT_JALT_NUM_ENTRIES relocations for cm.jalt in terms of the + total size saved. + + relax_trip 2 / JVT_PROFILING_DETERMINE: + Check if table jump can reduce the size, and delete the whole table + jump section if the size will not be reduced. + If table jump can save size, and then we replace all targeted + instructions/instruction pairs (e.g. auipc+jalr) to table jump + instructions with the index encoded. Then add relocations to the jump + table. + + relax_trip 3 / JVT_PROFILING_TRIM: + Trim unused slots in the table jump section. */ + + if (info->relax_pass == RELAX_PASS_TABLE_JUMP_PROFILING + && riscv_use_jvt (info)) + { + if (!riscv_ensure_jvt_htab (htab)) + goto fail; + jvt_htab = htab->jvt_htab; + + riscv_relax_delete_bytes = _riscv_relax_delete_immediate; + /* Avoid size benefits of relocations to be recorded multiple times. */ + if (info->relax_trip == JVT_PROFILING_RECORD_SYM + && *(htab->data_segment_phase) != 0) + return true; + + /* Rank the entries, and calculate the expected total saving. */ + else if (info->relax_trip == JVT_PROFILING_RANK) + { + *again = true; + /* Profiling stage finished. */ + if (jvt_htab->end_idx != 0) + return true; + + riscv_jvt_args args = {jvt_htab, 0, 0}; + /* Estimate size benefits if table jump is used. */ + riscv_jvt_profiling (jvt_htab, &args); + if (jvt_htab->end_idx > 0 + && (!bfd_set_section_alignment (jvt_htab->jvt_sec, 6) + || !bfd_set_section_size + (jvt_htab->jvt_sec, + (bfd_size_type) jvt_htab->end_idx + * RISCV_ELF_WORD_BYTES))) + goto fail; + return true; + } + + /* Generate table-jump instructions only if profiling chose a + positive-benefit table and sized .riscv.jvt. */ + else if (info->relax_trip == JVT_PROFILING_DETERMINE) + { + if (jvt_htab->end_idx <= 0 || jvt_htab->jvt_sec->size == 0) + return true; + + *again = true; + } + + /* Trim unused slots in the table jump section. */ + else if (info->relax_trip == JVT_PROFILING_TRIM) + { + /* Table jump entry section is trimmed. */ + if (jvt_htab->end_idx < 0) + return true; + + used_bytes = jvt_htab->end_idx * RISCV_ELF_WORD_BYTES; + if (jvt_htab->jvt_sec->size <= used_bytes) + { + jvt_htab->end_idx = -1; + return true; + } + + trimmed_bytes = jvt_htab->jvt_sec->size - used_bytes; + /* Trim unused slots. */ + if (!riscv_relax_delete_bytes (jvt_htab->jvt_sec->owner, + jvt_htab->jvt_sec, used_bytes, + trimmed_bytes, info, NULL, NULL, false)) + return false; + /* Mark table jump profiling stage as completed. */ + jvt_htab->end_idx = -1; + return true; + } + } + /* Examine and consider relaxing each reloc. */ for (i = 0; i < sec->reloc_count; i++) { @@ -4981,17 +5993,49 @@ _bfd_riscv_relax_section (bfd *abfd, asection *sec, relax_func = NULL; riscv_relax_delete_bytes = NULL; - if (info->relax_pass == 0) + if (info->relax_pass == RELAX_PASS_TABLE_JUMP_PROFILING) + { + if (!riscv_use_jvt (info)) + return true; + riscv_relax_delete_bytes = _riscv_relax_delete_immediate; + + if ((type == R_RISCV_CALL || type == R_RISCV_CALL_PLT + || type == R_RISCV_JAL) + && (i == sec->reloc_count - 1 + || ELFNN_R_TYPE ((rel + 1)->r_info) != R_RISCV_RELAX + || rel->r_offset != (rel + 1)->r_offset)) + continue; + + if (info->relax_trip == JVT_PROFILING_RECORD_SYM) + { + if (type == R_RISCV_CALL || type == R_RISCV_CALL_PLT + || type == R_RISCV_JAL) + relax_func = _bfd_riscv_jvt_record; + else + continue; + *again = true; + i++; + } + else if (info->relax_trip == JVT_PROFILING_DETERMINE) + { + if (type == R_RISCV_CALL || type == R_RISCV_CALL_PLT + || type == R_RISCV_JAL) + relax_func = _bfd_riscv_jvt_mark; + else + continue; + i++; + } + } + else if (info->relax_pass == RELAX_PASS_SHORTEN_LUI_CALL_TRREL_PCREL) { - if (type == R_RISCV_CALL - || type == R_RISCV_CALL_PLT) + if (type == R_RISCV_CALL || type == R_RISCV_CALL_PLT) relax_func = _bfd_riscv_relax_call; - else if (type == R_RISCV_HI20 - || type == R_RISCV_LO12_I + else if (type == R_RISCV_JAL) + relax_func = _bfd_riscv_relax_jal; + else if (type == R_RISCV_HI20 || type == R_RISCV_LO12_I || type == R_RISCV_LO12_S) relax_func = _bfd_riscv_relax_lui; - else if (type == R_RISCV_TPREL_HI20 - || type == R_RISCV_TPREL_ADD + else if (type == R_RISCV_TPREL_HI20 || type == R_RISCV_TPREL_ADD || type == R_RISCV_TPREL_LO12_I || type == R_RISCV_TPREL_LO12_S) relax_func = _bfd_riscv_relax_tls_le; @@ -5015,7 +6059,8 @@ _bfd_riscv_relax_section (bfd *abfd, asection *sec, /* Skip over the R_RISCV_RELAX. */ i++; } - else if (info->relax_pass == 1 && type == R_RISCV_ALIGN) + else if (info->relax_pass == RELAX_PASS_ALIGNMENT + && type == R_RISCV_ALIGN) { relax_func = _bfd_riscv_relax_align; riscv_relax_delete_bytes = _riscv_relax_delete_immediate; @@ -5025,20 +6070,6 @@ _bfd_riscv_relax_section (bfd *abfd, asection *sec, data->relocs = relocs; - /* Read this BFD's contents if we haven't done so already. */ - if (!data->this_hdr.contents - && !bfd_malloc_and_get_section (abfd, sec, &data->this_hdr.contents)) - goto fail; - - /* Read this BFD's symbols if we haven't done so already. */ - if (symtab_hdr->sh_info != 0 - && !symtab_hdr->contents - && !(symtab_hdr->contents = - (unsigned char *) bfd_elf_get_elf_syms (abfd, symtab_hdr, - symtab_hdr->sh_info, - 0, NULL, NULL, NULL))) - goto fail; - /* Get the value of the symbol referred to by the reloc. */ if (ELFNN_R_SYM (rel->r_info) < symtab_hdr->sh_info) { @@ -5384,6 +6415,36 @@ riscv_elf_obj_attrs_arg_type (obj_attr_tag_t tag) return (tag & 1) != 0 ? ATTR_TYPE_FLAG_STR_VAL : ATTR_TYPE_FLAG_INT_VAL; } +static bool +riscv_final_link (bfd *abfd, struct bfd_link_info *info) +{ + struct riscv_elf_link_hash_table *htab = riscv_elf_hash_table (info); + riscv_jvt_htab_t *jvt_htab = htab->jvt_htab; + + if (riscv_use_jvt (info) + && !riscv_define_jvt_base_symbol (abfd, info)) + return false; + + if (!_bfd_elf_final_link (abfd, info)) + return false; + + if (riscv_use_jvt (info) + && jvt_htab != NULL + && jvt_htab->jvt_sec != NULL + && jvt_htab->jvt_sec->size != 0 + && (jvt_htab->jvt_sec->flags & SEC_EXCLUDE) == 0) + { + asection *sec = jvt_htab->jvt_sec; + asection *out_sec = sec->output_section; + + if (!bfd_set_section_contents (abfd, out_sec, jvt_htab->jvt_addrs, + (file_ptr) sec->output_offset, sec->size)) + return false; + } + + return true; +} + /* Do not choose mapping symbols as a function name. */ static bfd_size_type @@ -5549,6 +6610,7 @@ elfNN_riscv_merge_gnu_properties (struct bfd_link_info *info, bfd *abfd, #define bfd_elfNN_mkobject elfNN_riscv_mkobject #define bfd_elfNN_get_synthetic_symtab \ elfNN_riscv_get_synthetic_symtab +#define bfd_elfNN_bfd_final_link riscv_final_link #define elf_backend_reloc_type_class riscv_reloc_type_class #define elf_backend_copy_indirect_symbol riscv_elf_copy_indirect_symbol From patchwork Sat Jun 27 10:45:53 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiawei X-Patchwork-Id: 137933 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from vm01.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id A50844BA23D0 for ; Sat, 27 Jun 2026 10:47:03 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org A50844BA23D0 X-Original-To: binutils@sourceware.org Delivered-To: binutils@sourceware.org Received: from cstnet.cn (smtp21.cstnet.cn [159.226.251.21]) by sourceware.org (Postfix) with ESMTPS id ABB7C4BA2E31 for ; Sat, 27 Jun 2026 10:46:27 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org ABB7C4BA2E31 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=iscas.ac.cn Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=iscas.ac.cn ARC-Filter: OpenARC Filter v1.0.0 sourceware.org ABB7C4BA2E31 Authentication-Results: sourceware.org; arc=none smtp.remote-ip=159.226.251.21 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1782557188; cv=none; b=tVMhNH31G/MVaeg3k4iFVle+xTcme6e+T25IFRPcG/972gWUkft9ybahhrp2PgXJQJ0aLQSCbqKXDY0ECRxEaKUzwKLqioayvW14ih+3vVWU7QfjEyFgRPABnC+sfHWKaBZJoJipmITonaJXveWYOwPqbIRgsLPx9vnOyA8j4jU= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1782557188; c=relaxed/simple; bh=J3dmOH/D48xFBpL3ipavINv/XkJ0wffMg5Hsl6RA2MM=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=hJhNS+y+G0Dwvd7AounoUxTX7q6br1dIZWRAwFCoWo6VoPKTEhhxKyCI5c4l7W298dryGyclwUp/Gz/FPrr4g6tu4EOSG9+8Qm9GsXurCGOdLOWtHMJfuIN6AM7DZZFxe7umsBQe4/xznkbKcDtVE5Z6FAu+w/VY7HptoyH9nnA= ARC-Authentication-Results: i=1; sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org ABB7C4BA2E31 Received: from localhost.localdomain (unknown [157.0.80.168]) by APP-01 (Coremail) with SMTP id qwCowACXMcr6qT9qMtWNAw--.25411S5; Sat, 27 Jun 2026 18:46:21 +0800 (CST) From: Jiawei To: binutils@sourceware.org Cc: nelson@rivosinc.com, jbeulich@suse.com, jeremy.bennett@embecosm.com, kito.cheng@sifive.com, mary.bennett@embecosm.com, nandni.jamnadas@embecosm.com, charlie.keaney@embecosm.com, hau.hsu@sifive.com, jerry.zhangjian@sifive.com, sinan.lin@linux.alibaba.com, Jiawei Subject: [RFC PATCH 3/5] ld: Add RISC-V --relax-zcmt option Date: Sat, 27 Jun 2026 18:45:53 +0800 Message-ID: <20260627104555.331493-4-jiawei@iscas.ac.cn> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260627104555.331493-1-jiawei@iscas.ac.cn> References: <20260627104555.331493-1-jiawei@iscas.ac.cn> MIME-Version: 1.0 X-CM-TRANSID: qwCowACXMcr6qT9qMtWNAw--.25411S5 X-Coremail-Antispam: 1UD129KBjvJXoW3WF43tr4xXF15XrW7WryfJFb_yoW7CF17pr 95W39ak3WrJrn7Jw17Aw409Fn5Cws3uF4rGr43Gw40ga9xZF1vqayYya47ua4kXrW8ur43 Wa42qr1UuFWfZrUanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUQa14x267AKxVWrJVCq3wAFc2x0x2IEx4CE42xK8VAvwI8IcIk0 rVWrJVCq3wAFIxvE14AKwVWUJVWUGwA2048vs2IY020E87I2jVAFwI0_JrWl82xGYIkIc2 x26xkF7I0E14v26ryj6s0DM28lY4IEw2IIxxk0rwA2F7IY1VAKz4vEj48ve4kI8wA2z4x0 Y4vE2Ix0cI8IcVAFwI0_Gr0_Xr1l84ACjcxK6xIIjxv20xvEc7CjxVAFwI0_Cr0_Gr1UM2 8EF7xvwVC2z280aVAFwI0_GcCE3s1l84ACjcxK6I8E87Iv6xkF7I0E14v26rxl6s0DM2AI xVAIcxkEcVAq07x20xvEncxIr21l5I8CrVACY4xI64kE6c02F40Ex7xfMcIj6xIIjxv20x vE14v26r1j6r18McIj6xkF7I0En7xvr7AKxVWUJVW8JwAv7VC2z280aVAFwI0_Jr0_Gr1l Ox8S6xCaFVCjc4AY6r1j6r4UM4x0Y48IcxkI7VAKI48JM4x0x7Aq67IIx4CEVc8vx2IErc IFxwACI402YVCY1x02628vn2kIc2xKxwCY1x0262kKe7AKxVWUtVW8ZwCF04k20xvY0x0E wIxGrwCFx2IqxVCFs4IE7xkEbVWUJVW8JwC20s026c02F40E14v26r1j6r18MI8I3I0E74 80Y4vE14v26r106r1rMI8E67AF67kF1VAFwI0_Jw0_GFylIxkGc2Ij64vIr41lIxAIcVC0 I7IYx2IY67AKxVWUJVWUCwCI42IY6xIIjxv20xvEc7CjxVAFwI0_Gr0_Cr1lIxAIcVCF04 k26cxKx2IYs7xG6r1j6r1xMIIF0xvEx4A2jsIE14v26r1j6r4UMIIF0xvEx4A2jsIEc7Cj xVAFwI0_Gr0_Gr1UYxBIdaVFxhVjvjDU0xZFpf9x0JUqoGQUUUUU= X-Originating-IP: [157.0.80.168] X-CM-SenderInfo: 5mld4v3l6l2u1dvotugofq/1tbiBwYLAGo-mHsfOAACsZ X-Spam-Status: No, score=-11.1 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, SPF_HELO_PASS, SPF_PASS, TXREP shortcircuit=no autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on sourceware.org X-BeenThere: binutils@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Binutils mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: binutils-bounces~patchwork=sourceware.org@sourceware.org Expose Zcmt table-jump relaxation as an explicit opt-in RISC-V linker option, and document the non-position-independent executable links and JVT CSR requirement, and keep the optimization disabled by default. ld/ChangeLog: * NEWS: Add --relax-zcmt entry. * emultempl/riscvelf.em: Handle --relax-zcmt option. * gen-doc.texi: Enable RISC-V docs. * ld.texi: Document --relax-zcmt. * ldlex.h (enum option_values): Add RELAX_ZCMT options. --- ld/NEWS | 3 +++ ld/emultempl/riscvelf.em | 17 +++++++++++++++-- ld/gen-doc.texi | 2 +- ld/ld.texi | 35 +++++++++++++++++++++++++++++++++++ ld/ldlex.h | 2 ++ 5 files changed, 56 insertions(+), 3 deletions(-) diff --git a/ld/NEWS b/ld/NEWS index 2de87ae227c..774eaf2c457 100644 --- a/ld/NEWS +++ b/ld/NEWS @@ -2,6 +2,9 @@ Changes in 2.47: +* Add the RISC-V --relax-zcmt option for opt-in Zcmt table-jump relaxation + in non-position-independent executable links. + * Add a linker optimization level of zero. Using "-O 0" on the linker command line will stop it from combining the contents of mergeable sections. This can significantly speed up the link process at the cost of producing larger diff --git a/ld/emultempl/riscvelf.em b/ld/emultempl/riscvelf.em index 814109355d9..67c9c23f289 100644 --- a/ld/emultempl/riscvelf.em +++ b/ld/emultempl/riscvelf.em @@ -26,7 +26,8 @@ fragment < X-Patchwork-Id: 137937 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from vm01.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 973144BA2E3B for ; Sat, 27 Jun 2026 10:49:32 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 973144BA2E3B X-Original-To: binutils@sourceware.org Delivered-To: binutils@sourceware.org Received: from cstnet.cn (smtp21.cstnet.cn [159.226.251.21]) by sourceware.org (Postfix) with ESMTPS id 9BB9C4BA2E2D for ; Sat, 27 Jun 2026 10:46:26 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 9BB9C4BA2E2D Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=iscas.ac.cn Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=iscas.ac.cn ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 9BB9C4BA2E2D Authentication-Results: sourceware.org; arc=none smtp.remote-ip=159.226.251.21 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1782557187; cv=none; b=NUMLvKwAH28I1g3EUz/QGsexqLPSRcLFIejJBd98Ebc+lChCNMxo17sxZ2ZQc5ln14YCDVpZJyqzuMv9p1d9Yl16GjmZsg/3LxYwVAsLm9NtbwL/BP/QFNtd0Z9TADot3GKxmnPC/8j/x3ITonToBz2JA4k42qeNuF07dquKFYg= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1782557187; c=relaxed/simple; bh=WCyiw5cYczkzMs65ON/HOmpEv+gfHuZurnDT/Lf29Zc=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=Afn3TngI5MbO0aO9pc6ZlvEAsPcBojLMR8deb23aKUg/FMOwUCmza9WlVBK5AT1hxDiSImpOH3x18BmsEeB2m8ShB42VFRWAwDrm+MR6Bvd/lHur0U+0KBLJKoeC6qr6OTv7F9W3Rg1Nd9bEII4lw+wSyRISEvRrUFimyEVYkA4= ARC-Authentication-Results: i=1; sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 9BB9C4BA2E2D Received: from localhost.localdomain (unknown [157.0.80.168]) by APP-01 (Coremail) with SMTP id qwCowACXMcr6qT9qMtWNAw--.25411S6; Sat, 27 Jun 2026 18:46:21 +0800 (CST) From: Jiawei To: binutils@sourceware.org Cc: nelson@rivosinc.com, jbeulich@suse.com, jeremy.bennett@embecosm.com, kito.cheng@sifive.com, mary.bennett@embecosm.com, nandni.jamnadas@embecosm.com, charlie.keaney@embecosm.com, hau.hsu@sifive.com, jerry.zhangjian@sifive.com, sinan.lin@linux.alibaba.com, Jiawei Subject: [RFC PATCH 4/5] RISC-V: Decode Zcmt JVT entries in objdump Date: Sat, 27 Jun 2026 18:45:54 +0800 Message-ID: <20260627104555.331493-5-jiawei@iscas.ac.cn> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260627104555.331493-1-jiawei@iscas.ac.cn> References: <20260627104555.331493-1-jiawei@iscas.ac.cn> MIME-Version: 1.0 X-CM-TRANSID: qwCowACXMcr6qT9qMtWNAw--.25411S6 X-Coremail-Antispam: 1UD129KBjvJXoW3WF18JFyxXr17CryDZFyrJFb_yoW3tw1Up3 98KrWrGr1rJF1xurs3Cr1rAFsxtrWkK3Z0q347WFWxCr1I93yFqF4kKFyS9a98Grs5Aw1a yan0yr47urs5CF7anT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUQm14x267AKxVWrJVCq3wAFc2x0x2IEx4CE42xK8VAvwI8IcIk0 rVWrJVCq3wAFIxvE14AKwVWUJVWUGwA2048vs2IY020E87I2jVAFwI0_JF0E3s1l82xGYI kIc2x26xkF7I0E14v26ryj6s0DM28lY4IEw2IIxxk0rwA2F7IY1VAKz4vEj48ve4kI8wA2 z4x0Y4vE2Ix0cI8IcVAFwI0_Gr0_Xr1l84ACjcxK6xIIjxv20xvEc7CjxVAFwI0_Cr0_Gr 1UM28EF7xvwVC2z280aVAFwI0_GcCE3s1l84ACjcxK6I8E87Iv6xkF7I0E14v26rxl6s0D M2AIxVAIcxkEcVAq07x20xvEncxIr21l5I8CrVACY4xI64kE6c02F40Ex7xfMcIj6xIIjx v20xvE14v26r1j6r18McIj6xkF7I0En7xvr7AKxVWUJVW8JwAv7VC2z280aVAFwI0_Jr0_ Gr1lOx8S6xCaFVCjc4AY6r1j6r4UM4x0Y48IcxkI7VAKI48JM4x0x7Aq67IIx4CEVc8vx2 IErcIFxwACI402YVCY1x02628vn2kIc2xKxwCY1x0262kKe7AKxVWUtVW8ZwCF04k20xvY 0x0EwIxGrwCFx2IqxVCFs4IE7xkEbVWUJVW8JwC20s026c02F40E14v26r1j6r18MI8I3I 0E7480Y4vE14v26r106r1rMI8E67AF67kF1VAFwI0_Jw0_GFylIxkGc2Ij64vIr41lIxAI cVC0I7IYx2IY67AKxVWUJVWUCwCI42IY6xIIjxv20xvEc7CjxVAFwI0_Cr0_Gr1UMIIF0x vE42xK8VAvwI8IcIk0rVWUJVWUCwCI42IY6I8E87Iv67AKxVWUJVW8JwCI42IY6I8E87Iv 6xkF7I0E14v26r4j6r4UJbIYCTnIWIevJa73UjIFyTuYvjfUeKsbUUUUU X-Originating-IP: [157.0.80.168] X-CM-SenderInfo: 5mld4v3l6l2u1dvotugofq/1tbiDAALAGo-mA8f+gAAsg X-Spam-Status: No, score=-11.2 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, SPF_HELO_PASS, SPF_PASS, TXREP shortcircuit=no autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on sourceware.org X-BeenThere: binutils@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Binutils mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: binutils-bounces~patchwork=sourceware.org@sourceware.org This patch adds the RISC-V disassembler to print JVT table entries and annotate cm.jt and cm.jalt targets when the table is present. opcodes/ChangeLog: * riscv-dis.c (struct riscv_private_data): Add JVT fields. (riscv_set_xlen_from_elf): New function. (maybe_print_jvt_address): Ditto. (print_insn_args): Annotate JVT target. (riscv_disassemble_insn): Handle Zcmt decode. (riscv_disassemble_jvt): New function. (riscv_init_disasm_info): Init JVT data. (print_insn_riscv): Handle JVT section. (disassemble_free_riscv): Free JVT content. --- opcodes/riscv-dis.c | 164 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 149 insertions(+), 15 deletions(-) diff --git a/opcodes/riscv-dis.c b/opcodes/riscv-dis.c index ca0d9bfd121..5d5ff0f8b3c 100644 --- a/opcodes/riscv-dis.c +++ b/opcodes/riscv-dis.c @@ -47,6 +47,10 @@ struct riscv_private_data bfd_vma hi_addr[OP_MASK_RD + 1]; bool to_print_addr; bool has_gp; + bool has_jvt_base; + asection *jvt_section; + bfd_byte *jvt_content; + bfd_size_type jvt_size; /* Current XLEN for the disassembler. */ unsigned xlen; /* Default ISA specification version. */ @@ -220,6 +224,48 @@ maybe_print_address (struct riscv_private_data *pd, int base_reg, int offset, pd->print_addr = (bfd_vma)(uint32_t)pd->print_addr; } +/* Set pd->xlen from ELF class if not already known. */ + +static void +riscv_set_xlen_from_elf (struct riscv_private_data *pd, + struct disassemble_info *info) +{ + if (pd->xlen != 0) + return; + + if (info->mach == bfd_mach_riscv64) + pd->xlen = 64; + else if (info->mach == bfd_mach_riscv32) + pd->xlen = 32; + else if (info->section != NULL) + { + Elf_Internal_Ehdr *ehdr = elf_elfheader (info->section->owner); + pd->xlen = ehdr->e_ident[EI_CLASS] == ELFCLASS64 ? 64 : 32; + } +} + +/* Try to print target address of cm.jalt and cm.jt. */ + +static void +maybe_print_jvt_address (struct riscv_private_data *pd, int index) +{ + if (!pd->has_jvt_base || pd->jvt_section == NULL || pd->jvt_content == NULL + || pd->xlen == 0) + return; + + bfd_size_type entry_size = pd->xlen / 8; + bfd_size_type offset = entry_size * (bfd_size_type) index; + if (index < 0 || index > (ZCMT_TOTAL_ENTRIES - 1) + || offset + entry_size > pd->jvt_size) + return; + + bfd_byte *packet = pd->jvt_content + offset; + + pd->to_print_addr = true; + pd->print_addr = bfd_get_bits (packet, pd->xlen, + bfd_big_endian (pd->jvt_section->owner)); +} + /* Get Zcmp reg_list field. */ static void @@ -747,6 +793,7 @@ print_insn_args (const char *oparg, insn_t l, bfd_vma pc, disassemble_info *info case 'I': print (info->stream, dis_style_address_offset, "%" PRIu64, EXTRACT_ZCMT_INDEX (l)); + maybe_print_jvt_address (pd, EXTRACT_ZCMT_INDEX (l)); break; default: goto undefined_modifier; @@ -1052,17 +1099,7 @@ riscv_disassemble_insn (bfd_vma memaddr, if (op != NULL) { /* If XLEN is not known, get its value from the ELF class. */ - if (pd->xlen != 0) - ; - else if (info->mach == bfd_mach_riscv64) - pd->xlen = 64; - else if (info->mach == bfd_mach_riscv32) - pd->xlen = 32; - else if (info->section != NULL) - { - Elf_Internal_Ehdr *ehdr = elf_elfheader (info->section->owner); - pd->xlen = ehdr->e_ident[EI_CLASS] == ELFCLASS64 ? 64 : 32; - } + riscv_set_xlen_from_elf (pd, info); /* If arch has the Zfinx extension, replace FPR with GPR. */ if (riscv_subset_supports (&pd->riscv_rps_dis, "zfinx")) @@ -1086,10 +1123,12 @@ riscv_disassemble_insn (bfd_vma memaddr, if ((op->xlen_requirement != 0) && (op->xlen_requirement != pd->xlen)) continue; - /* Is this instruction supported by the current architecture? */ + /* Is this instruction supported by the current architecture? + Always disassemble ZCMT instructions if __jvt_base$ is present. */ if (!pd->all_ext && !riscv_multi_subset_supports (&pd->riscv_rps_dis, - op->insn_class)) + op->insn_class) + && !(pd->has_jvt_base && op->insn_class == INSN_CLASS_ZCMT)) continue; /* It's a match. */ @@ -1481,6 +1520,51 @@ riscv_disassemble_data (bfd_vma memaddr ATTRIBUTE_UNUSED, return info->bytes_per_chunk; } +/* DATA is the function address in jump table entry. + Lookup the address in symbols and print the function name. */ +static int +riscv_disassemble_jvt (bfd_vma memaddr, insn_t data, + const bfd_byte *packet, + disassemble_info *info) +{ + struct riscv_private_data *pd = info->private_data; + if (pd == NULL || pd->xlen == 0 || info->section == NULL) + return -1; + + bfd_size_type entry_size = pd->xlen / 8; + bfd_vma offset = memaddr - info->section->vma; + bfd_size_type entry_offset = (offset / entry_size) * entry_size; + bfd_size_type entry_delta = offset - entry_offset; + int idx = entry_offset / entry_size; + if (idx < 0 || idx > (ZCMT_TOTAL_ENTRIES - 1)) + opcodes_error_handler (_ ("invalid jvt index: %i"), idx); + + const char *inst_str; + if (idx <= ZCMT_JT_END) + inst_str = "jvt.jt"; + else + inst_str = "jvt.jalt"; + + if (pd->jvt_content != NULL && entry_offset + entry_size <= pd->jvt_size) + packet = pd->jvt_content + entry_offset; + data = bfd_get_bits (packet, pd->xlen, + bfd_big_endian (info->section->owner)); + + const char *funcname = ""; + for (int i = 0; i < info->symtab_size; i++) + { + bfd_vma addr = bfd_asymbol_value (info->symtab[i]); + if (addr == (bfd_vma) data) + { + funcname = info->symtab[i]->name; + break; + } + } + (*info->fprintf_styled_func) (info->stream, dis_style_text, "%s[%i]:\t%s", + inst_str, idx, funcname); + return entry_size - entry_delta; +} + static bool riscv_init_disasm_info (struct disassemble_info *info) { @@ -1493,7 +1577,34 @@ riscv_init_disasm_info (struct disassemble_info *info) pd->hi_addr[i] = -1; pd->to_print_addr = false; + pd->has_jvt_base = false; pd->has_gp = false; + pd->jvt_section = NULL; + pd->jvt_content = NULL; + pd->jvt_size = 0; + + if (info->section != NULL) + { + bfd *abfd = info->section->owner; + if (abfd && bfd_get_flavour (abfd) == bfd_target_elf_flavour) + { + asection *s = bfd_get_section_by_name (abfd, TABLE_JUMP_SEC_NAME); + if (s != NULL && bfd_section_size (s) > 0) + { + bfd_size_type size = bfd_section_size (s); + bfd_byte *buf = (bfd_byte *) xmalloc (size); + if (bfd_get_section_contents (abfd, s, buf, 0, size)) + { + pd->jvt_section = s; + pd->jvt_content = buf; + pd->jvt_size = size; + } + else + free (buf); + } + } + } + for (i = 0; i < info->symtab_size; i++) { asymbol *sym = info->symtab[i]; @@ -1502,9 +1613,18 @@ riscv_init_disasm_info (struct disassemble_info *info) pd->gp = bfd_asymbol_value (sym); pd->has_gp = true; } + + if (strcmp (bfd_asymbol_name (sym), RISCV_TABLE_JUMP_BASE_SYMBOL) == 0) + { + bfd_vma jvt_base = bfd_asymbol_value (sym); + if (pd->jvt_section != NULL + && jvt_base == bfd_section_vma (pd->jvt_section)) + pd->has_jvt_base = true; + } } pd->xlen = 0; + riscv_set_xlen_from_elf (pd, info); pd->default_isa_spec = ISA_SPEC_CLASS_DRAFT - 1; pd->default_priv_spec = PRIV_SPEC_CLASS_NONE; @@ -1598,8 +1718,21 @@ print_insn_riscv (bfd_vma memaddr, struct disassemble_info *info) ((struct riscv_private_data *) info->private_data)->last_map_state = mstate; /* Set the size to dump. */ - if (mstate == MAP_DATA - && (info->flags & DISASSEMBLE_DATA) == 0) + if (info->section != NULL + && strcmp (info->section->name, TABLE_JUMP_SEC_NAME) == 0) + { + struct riscv_private_data *pd = info->private_data; + riscv_set_xlen_from_elf (pd, info); + + dump_size = pd->xlen / 8; + info->bytes_per_chunk = dump_size; + info->bytes_per_line = dump_size; + info->endian_code = bfd_big_endian (info->section->owner) + ? BFD_ENDIAN_BIG : BFD_ENDIAN_LITTLE; + info->display_endian = info->endian_code; + riscv_disassembler = riscv_disassemble_jvt; + } + else if (mstate == MAP_DATA && (info->flags & DISASSEMBLE_DATA) == 0) { dump_size = riscv_data_length (memaddr, info); info->bytes_per_chunk = dump_size; @@ -1829,5 +1962,6 @@ void disassemble_free_riscv (struct disassemble_info *info ATTRIBUTE_UNUSED) { riscv_release_subset_list (pd->riscv_rps_dis.subset_list); free (pd->riscv_rps_dis.subset_list); + free (pd->jvt_content); } } From patchwork Sat Jun 27 10:45:55 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiawei X-Patchwork-Id: 137934 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from vm01.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 14E9A4BA23C2 for ; Sat, 27 Jun 2026 10:47:24 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 14E9A4BA23C2 X-Original-To: binutils@sourceware.org Delivered-To: binutils@sourceware.org Received: from cstnet.cn (smtp21.cstnet.cn [159.226.251.21]) by sourceware.org (Postfix) with ESMTPS id A88884BA2E35 for ; Sat, 27 Jun 2026 10:46:28 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org A88884BA2E35 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=iscas.ac.cn Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=iscas.ac.cn ARC-Filter: OpenARC Filter v1.0.0 sourceware.org A88884BA2E35 Authentication-Results: sourceware.org; arc=none smtp.remote-ip=159.226.251.21 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1782557190; cv=none; b=qy6gAa+PM3/kOHu7Jwo5NyR3x4pP49Or0JzRYVVYQtzWwb45KqaIt0/mvE4m/IwdzbWJaG4/cxj/36xJZXgxOVaAtzqpw0Bm8+9W0Ori+tNXp6hHxe++sYLbfJN1qQi0PW/wmYuVMpKkkWZHSIM32e7Z05B1VZA07b1LEU9yaZQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1782557190; c=relaxed/simple; bh=enMU5+PIpvRFIWIanodEZnaA9JKYDM5Xy5RX822IKZk=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=id7tez56osLkgSLuVv9GccF+tSMW6eqlQ/tvsNlklprju2QZaGLsCcr9BjR5C04e0VgKJA6UPnjrQrGRCV1RIpAd/68FmCV+PdISBNRfRae2YEVB1ZPAS2u01YmEETAWDehfLS6hBA6z4myQ6LbYtpBCnNlpaZNCMDEbdpv6Wgk= ARC-Authentication-Results: i=1; sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org A88884BA2E35 Received: from localhost.localdomain (unknown [157.0.80.168]) by APP-01 (Coremail) with SMTP id qwCowACXMcr6qT9qMtWNAw--.25411S7; Sat, 27 Jun 2026 18:46:22 +0800 (CST) From: Jiawei To: binutils@sourceware.org Cc: nelson@rivosinc.com, jbeulich@suse.com, jeremy.bennett@embecosm.com, kito.cheng@sifive.com, mary.bennett@embecosm.com, nandni.jamnadas@embecosm.com, charlie.keaney@embecosm.com, hau.hsu@sifive.com, jerry.zhangjian@sifive.com, sinan.lin@linux.alibaba.com, Jiawei Subject: [RFC PATCH 5/5] RISC-V: Add Zcmt table-jump linker tests Date: Sat, 27 Jun 2026 18:45:55 +0800 Message-ID: <20260627104555.331493-6-jiawei@iscas.ac.cn> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260627104555.331493-1-jiawei@iscas.ac.cn> References: <20260627104555.331493-1-jiawei@iscas.ac.cn> MIME-Version: 1.0 X-CM-TRANSID: qwCowACXMcr6qT9qMtWNAw--.25411S7 X-Coremail-Antispam: 1UD129KBjvAXoWDGr4xtFy7tr48XF47trWUJwb_yoWxGF47Jo WDJayYva1rursFkr15A3yUAr4UGF1xKF47XFs8Cr4kua1q9a4rGry0yan8A34DZr1UCrWk WFy5Zasru3W0qwnrn29KB7ZKAUJUUUU8529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 AaLaJ3UjIYCTnIWjp_UUUOQ7AC8VAFwI0_Wr0E3s1l1xkIjI8I6I8E6xAIw20EY4v20xva j40_Wr0E3s1l1IIY67AEw4v_Jr0_Jr4l82xGYIkIc2x26280x7IE14v26r126s0DM28Irc Ia0xkI8VCY1x0267AKxVW5JVCq3wA2ocxC64kIII0Yj41l84x0c7CEw4AK67xGY2AK021l 84ACjcxK6xIIjxv20xvE14v26r4j6ryUM28EF7xvwVC0I7IYx2IY6xkF7I0E14v26F4j6r 4UJwA2z4x0Y4vEx4A2jsIE14v26rxl6s0DM28EF7xvwVC2z280aVCY1x0267AKxVW0oVCq 3wAS0I0E0xvYzxvE52x082IY62kv0487Mc02F40EFcxC0VAKzVAqx4xG6I80ewAv7VC0I7 IYx2IY67AKxVWUJVWUGwAv7VCY1x0262k0Y48FwI0_Jr0_Gr1lYx0Ex4A2jsIE14v26r1j 6r4UMcvjeVCFs4IE7xkEbVWUJVW8JwACjcxG0xvY0x0EwIxGrwACjI8F5VA0II8E6IAqYI 8I648v4I1lFIxGxcIEc7CjxVA2Y2ka0xkIwI1lc7CjxVAaw2AFwI0_Jw0_GFyl42xK82IY c2Ij64vIr41l4I8I3I0E4IkC6x0Yz7v_Jr0_Gr1lx2IqxVAqx4xG67AKxVWUJVWUGwC20s 026x8GjcxK67AKxVWUGVWUWwC2zVAF1VAY17CE14v26r1q6r43MIIYrxkI7VAKI48JMIIF 0xvE2Ix0cI8IcVAFwI0_JFI_Gr1lIxAIcVC0I7IYx2IY6xkF7I0E14v26F4j6r4UJwCI42 IY6xAIw20EY4v20xvaj40_Jr0_JF4lIxAIcVC2z280aVAFwI0_Jr0_Gr1lIxAIcVC2z280 aVCY1x0267AKxVW8JVW8JrUvcSsGvfC2KfnxnUUI43ZEXa7VUjiIDDUUUUU== X-Originating-IP: [157.0.80.168] X-CM-SenderInfo: 5mld4v3l6l2u1dvotugofq/1tbiBwcLAGo-mHsfPAAAse X-Spam-Status: No, score=-11.1 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, PROLO_LEO1, SPF_HELO_PASS, SPF_PASS, TXREP shortcircuit=no autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on sourceware.org X-BeenThere: binutils@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Binutils mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: binutils-bounces~patchwork=sourceware.org@sourceware.org This patch adds zcmt table jump relaxation tests. Cover opt-in behavior, profitability, RV32/RV64 table emission, no-benefit and no-Zcmt cases, PIC/shared negative behavior, section layout, symbol policy, addends, GC, overflow, and the Zcd encoding conflict. ld/ChangeLog: * testsuite/ld-riscv-elf/ld-riscv-elf.exp: Add Zcmt tests. * testsuite/ld-riscv-elf/table-jump-addend.d: New test. * testsuite/ld-riscv-elf/table-jump-addend.s: New test. * testsuite/ld-riscv-elf/table-jump-base-collision.d: New test. * testsuite/ld-riscv-elf/table-jump-base-collision.s: New test. * testsuite/ld-riscv-elf/table-jump-base-local-collision.d: New test. * testsuite/ld-riscv-elf/table-jump-base-local-collision.s: New test. * testsuite/ld-riscv-elf/table-jump-be32-bytes.d: New test. * testsuite/ld-riscv-elf/table-jump-be32-text.d: New test. * testsuite/ld-riscv-elf/table-jump-be64-bytes.d: New test. * testsuite/ld-riscv-elf/table-jump-be64-text.d: New test. * testsuite/ld-riscv-elf/table-jump-benefit.d: New test. * testsuite/ld-riscv-elf/table-jump-benefit.s: New test. * testsuite/ld-riscv-elf/table-jump-default-jvt-relocs.d: New test. * testsuite/ld-riscv-elf/table-jump-default-jvt-symbol.d: New test. * testsuite/ld-riscv-elf/table-jump-default-jvt.d: New test. * testsuite/ld-riscv-elf/table-jump-default-no-jvt.d: New test. * testsuite/ld-riscv-elf/table-jump-dump-unknown.d: New test. * testsuite/ld-riscv-elf/table-jump-emit-relocs.d: New test. * testsuite/ld-riscv-elf/table-jump-equal-benefit.d: New test. * testsuite/ld-riscv-elf/table-jump-equal-benefit.s: New test. * testsuite/ld-riscv-elf/table-jump-gc-comdat-symbol.d: New test. * testsuite/ld-riscv-elf/table-jump-gc-comdat.d: New test. * testsuite/ld-riscv-elf/table-jump-gc-comdat.s: New test. * testsuite/ld-riscv-elf/table-jump-gc-dead-symbol.d: New test. * testsuite/ld-riscv-elf/table-jump-gc-dead.d: New test. * testsuite/ld-riscv-elf/table-jump-gc-dead.s: New test. * testsuite/ld-riscv-elf/table-jump-jalt.d: New test. * testsuite/ld-riscv-elf/table-jump-jt.d: New test. * testsuite/ld-riscv-elf/table-jump-multiple-local-sym-2.s: New test. * testsuite/ld-riscv-elf/table-jump-multiple-local-sym.d: New test. * testsuite/ld-riscv-elf/table-jump-multiple-local-sym.s: New test. * testsuite/ld-riscv-elf/table-jump-no-benefit-jvt-ref.d: New test. * testsuite/ld-riscv-elf/table-jump-no-benefit-jvt-ref.s: New test. * testsuite/ld-riscv-elf/table-jump-no-benefit-section.d: New test. * testsuite/ld-riscv-elf/table-jump-no-benefit-symbol.d: New test. * testsuite/ld-riscv-elf/table-jump-no-benefit.s: New test. * testsuite/ld-riscv-elf/table-jump-no-relax-zcmt.d: New test. * testsuite/ld-riscv-elf/table-jump-no-relo-1.s: New test. * testsuite/ld-riscv-elf/table-jump-no-relo-2.s: New test. * testsuite/ld-riscv-elf/table-jump-no-relo.d: New test. * testsuite/ld-riscv-elf/table-jump-no-zcmt.d: New test. * testsuite/ld-riscv-elf/table-jump-no-zcmt.s: New test. * testsuite/ld-riscv-elf/table-jump-norelax.d: New test. * testsuite/ld-riscv-elf/table-jump-norelax.s: New test. * testsuite/ld-riscv-elf/table-jump-overflow.d: New test. * testsuite/ld-riscv-elf/table-jump-overflow.s: New test. * testsuite/ld-riscv-elf/table-jump-pie-relocs.d: New test. * testsuite/ld-riscv-elf/table-jump-pie-text.d: New test. * testsuite/ld-riscv-elf/table-jump-pie.d: New test. * testsuite/ld-riscv-elf/table-jump-pie.s: New test. * testsuite/ld-riscv-elf/table-jump-relax-zcmt.d: New test. * testsuite/ld-riscv-elf/table-jump-rv32.d: New test. * testsuite/ld-riscv-elf/table-jump-rv32.s: New test. * testsuite/ld-riscv-elf/table-jump-shared-relocs.d: New test. * testsuite/ld-riscv-elf/table-jump-shared-symbol.d: New test. * testsuite/ld-riscv-elf/table-jump-shared-text.d: New test. * testsuite/ld-riscv-elf/table-jump-shared.d: New test. * testsuite/ld-riscv-elf/table-jump-shared.s: New test. * testsuite/ld-riscv-elf/table-jump-strip-symbol.d: New test. * testsuite/ld-riscv-elf/table-jump-symbol-policy.d: New test. * testsuite/ld-riscv-elf/table-jump-vma-lma.d: New test. * testsuite/ld-riscv-elf/table-jump-vma-lma.ld: New test. * testsuite/ld-riscv-elf/table-jump-vma-zero.d: New test. * testsuite/ld-riscv-elf/table-jump-vma-zero.ld: New test. * testsuite/ld-riscv-elf/table-jump-vma-zero.s: New test. * testsuite/ld-riscv-elf/table-jump-zcd-conflict.d: New test. * testsuite/ld-riscv-elf/table-jump-zcmt-no-zca.d: New test. * testsuite/ld-riscv-elf/table-jump-zcmt-no-zca.s: New test. * testsuite/ld-riscv-elf/table-jump-zcmt-no-zicsr.d: New test. * testsuite/ld-riscv-elf/table-jump-zcmt-no-zicsr.s: New test. * testsuite/ld-riscv-elf/table-jump.ld: New test. * testsuite/ld-riscv-elf/table-jump.s: New test. --- ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp | 50 ++++++++++++++++++ ld/testsuite/ld-riscv-elf/table-jump-addend.d | 18 +++++++ ld/testsuite/ld-riscv-elf/table-jump-addend.s | 21 ++++++++ .../ld-riscv-elf/table-jump-base-collision.d | 4 ++ .../ld-riscv-elf/table-jump-base-collision.s | 18 +++++++ .../table-jump-base-local-collision.d | 4 ++ .../table-jump-base-local-collision.s | 17 +++++++ .../ld-riscv-elf/table-jump-be32-bytes.d | 10 ++++ .../ld-riscv-elf/table-jump-be32-text.d | 13 +++++ .../ld-riscv-elf/table-jump-be64-bytes.d | 10 ++++ .../ld-riscv-elf/table-jump-be64-text.d | 13 +++++ .../ld-riscv-elf/table-jump-benefit.d | 17 +++++++ .../ld-riscv-elf/table-jump-benefit.s | 51 +++++++++++++++++++ .../table-jump-default-jvt-relocs.d | 9 ++++ .../table-jump-default-jvt-symbol.d | 10 ++++ .../ld-riscv-elf/table-jump-default-jvt.d | 12 +++++ .../ld-riscv-elf/table-jump-default-no-jvt.d | 15 ++++++ .../ld-riscv-elf/table-jump-dump-unknown.d | 25 +++++++++ .../ld-riscv-elf/table-jump-emit-relocs.d | 9 ++++ .../ld-riscv-elf/table-jump-equal-benefit.d | 18 +++++++ .../ld-riscv-elf/table-jump-equal-benefit.s | 19 +++++++ .../table-jump-gc-comdat-symbol.d | 9 ++++ .../ld-riscv-elf/table-jump-gc-comdat.d | 11 ++++ .../ld-riscv-elf/table-jump-gc-comdat.s | 18 +++++++ .../ld-riscv-elf/table-jump-gc-dead-symbol.d | 9 ++++ .../ld-riscv-elf/table-jump-gc-dead.d | 11 ++++ .../ld-riscv-elf/table-jump-gc-dead.s | 18 +++++++ ld/testsuite/ld-riscv-elf/table-jump-jalt.d | 18 +++++++ ld/testsuite/ld-riscv-elf/table-jump-jt.d | 23 +++++++++ .../table-jump-multiple-local-sym-2.s | 12 +++++ .../table-jump-multiple-local-sym.d | 16 ++++++ .../table-jump-multiple-local-sym.s | 18 +++++++ .../table-jump-no-benefit-jvt-ref.d | 4 ++ .../table-jump-no-benefit-jvt-ref.s | 16 ++++++ .../table-jump-no-benefit-section.d | 9 ++++ .../table-jump-no-benefit-symbol.d | 9 ++++ .../ld-riscv-elf/table-jump-no-benefit.s | 12 +++++ .../ld-riscv-elf/table-jump-no-relax-zcmt.d | 17 +++++++ .../ld-riscv-elf/table-jump-no-relo-1.s | 7 +++ .../ld-riscv-elf/table-jump-no-relo-2.s | 12 +++++ .../ld-riscv-elf/table-jump-no-relo.d | 16 ++++++ .../ld-riscv-elf/table-jump-no-zcmt.d | 16 ++++++ .../ld-riscv-elf/table-jump-no-zcmt.s | 16 ++++++ .../ld-riscv-elf/table-jump-norelax.d | 15 ++++++ .../ld-riscv-elf/table-jump-norelax.s | 17 +++++++ .../ld-riscv-elf/table-jump-overflow.d | 11 ++++ .../ld-riscv-elf/table-jump-overflow.s | 49 ++++++++++++++++++ .../ld-riscv-elf/table-jump-pie-relocs.d | 9 ++++ .../ld-riscv-elf/table-jump-pie-text.d | 9 ++++ ld/testsuite/ld-riscv-elf/table-jump-pie.d | 9 ++++ ld/testsuite/ld-riscv-elf/table-jump-pie.s | 13 +++++ .../ld-riscv-elf/table-jump-relax-zcmt.d | 23 +++++++++ ld/testsuite/ld-riscv-elf/table-jump-rv32.d | 15 ++++++ ld/testsuite/ld-riscv-elf/table-jump-rv32.s | 25 +++++++++ .../ld-riscv-elf/table-jump-shared-relocs.d | 9 ++++ .../ld-riscv-elf/table-jump-shared-symbol.d | 9 ++++ .../ld-riscv-elf/table-jump-shared-text.d | 9 ++++ ld/testsuite/ld-riscv-elf/table-jump-shared.d | 12 +++++ ld/testsuite/ld-riscv-elf/table-jump-shared.s | 15 ++++++ .../ld-riscv-elf/table-jump-strip-symbol.d | 9 ++++ .../ld-riscv-elf/table-jump-symbol-policy.d | 8 +++ .../ld-riscv-elf/table-jump-vma-lma.d | 16 ++++++ .../ld-riscv-elf/table-jump-vma-lma.ld | 10 ++++ .../ld-riscv-elf/table-jump-vma-zero.d | 15 ++++++ .../ld-riscv-elf/table-jump-vma-zero.ld | 13 +++++ .../ld-riscv-elf/table-jump-vma-zero.s | 14 +++++ .../ld-riscv-elf/table-jump-zcd-conflict.d | 9 ++++ .../ld-riscv-elf/table-jump-zcmt-no-zca.d | 9 ++++ .../ld-riscv-elf/table-jump-zcmt-no-zca.s | 24 +++++++++ .../ld-riscv-elf/table-jump-zcmt-no-zicsr.d | 9 ++++ .../ld-riscv-elf/table-jump-zcmt-no-zicsr.s | 24 +++++++++ ld/testsuite/ld-riscv-elf/table-jump.ld | 16 ++++++ ld/testsuite/ld-riscv-elf/table-jump.s | 46 +++++++++++++++++ 73 files changed, 1131 insertions(+) create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-addend.d create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-addend.s create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-base-collision.d create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-base-collision.s create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-base-local-collision.d create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-base-local-collision.s create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-be32-bytes.d create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-be32-text.d create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-be64-bytes.d create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-be64-text.d create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-benefit.d create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-benefit.s create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-default-jvt-relocs.d create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-default-jvt-symbol.d create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-default-jvt.d create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-default-no-jvt.d create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-dump-unknown.d create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-emit-relocs.d create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-equal-benefit.d create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-equal-benefit.s create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-gc-comdat-symbol.d create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-gc-comdat.d create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-gc-comdat.s create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-gc-dead-symbol.d create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-gc-dead.d create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-gc-dead.s create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-jalt.d create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-jt.d create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-multiple-local-sym-2.s create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-multiple-local-sym.d create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-multiple-local-sym.s create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-no-benefit-jvt-ref.d create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-no-benefit-jvt-ref.s create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-no-benefit-section.d create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-no-benefit-symbol.d create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-no-benefit.s create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-no-relax-zcmt.d create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-no-relo-1.s create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-no-relo-2.s create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-no-relo.d create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-no-zcmt.d create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-no-zcmt.s create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-norelax.d create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-norelax.s create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-overflow.d create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-overflow.s create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-pie-relocs.d create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-pie-text.d create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-pie.d create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-pie.s create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-relax-zcmt.d create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-rv32.d create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-rv32.s create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-shared-relocs.d create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-shared-symbol.d create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-shared-text.d create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-shared.d create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-shared.s create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-strip-symbol.d create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-symbol-policy.d create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-vma-lma.d create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-vma-lma.ld create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-vma-zero.d create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-vma-zero.ld create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-vma-zero.s create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-zcd-conflict.d create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-zcmt-no-zca.d create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-zcmt-no-zca.s create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-zcmt-no-zicsr.d create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-zcmt-no-zicsr.s create mode 100644 ld/testsuite/ld-riscv-elf/table-jump.ld create mode 100644 ld/testsuite/ld-riscv-elf/table-jump.s diff --git a/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp b/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp index 8e26ccff10a..32f953aba78 100644 --- a/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp +++ b/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp @@ -182,11 +182,60 @@ if [istarget "riscv*-*-*"] { "-march=rv64i -mabi=lp64" {weakref64.s} \ {{objdump -d weakref64.d}} "weakref64"]] + # Zcmt (jump table) tests. + run_dump_test "table-jump-jalt" + run_dump_test "table-jump-jt" + run_dump_test "table-jump-dump-unknown" + run_dump_test "table-jump-no-relo" + run_dump_test "table-jump-relax-zcmt" + run_dump_test "table-jump-no-relax-zcmt" + run_dump_test "table-jump-multiple-local-sym" + run_dump_test "table-jump-benefit" + run_dump_test "table-jump-addend" + run_dump_test "table-jump-norelax" + run_dump_test "table-jump-no-zcmt" + run_dump_test "table-jump-zcmt-no-zca" + run_dump_test "table-jump-zcmt-no-zicsr" + run_dump_test "table-jump-zcd-conflict" + run_dump_test "table-jump-overflow" + run_dump_test "table-jump-equal-benefit" + run_dump_test "table-jump-rv32" + run_dump_test "table-jump-vma-zero" + run_dump_test "table-jump-emit-relocs" + run_dump_test "table-jump-be64-bytes" + run_dump_test "table-jump-be64-text" + run_dump_test "table-jump-be32-bytes" + run_dump_test "table-jump-be32-text" + run_dump_test "table-jump-no-benefit-symbol" + run_dump_test "table-jump-no-benefit-section" + run_dump_test "table-jump-no-benefit-jvt-ref" + run_dump_test "table-jump-default-no-jvt" + run_dump_test "table-jump-default-jvt" + run_dump_test "table-jump-default-jvt-symbol" + run_dump_test "table-jump-default-jvt-relocs" + run_dump_test "table-jump-base-collision" + run_dump_test "table-jump-base-local-collision" + run_dump_test "table-jump-symbol-policy" + run_dump_test "table-jump-strip-symbol" + run_dump_test "table-jump-gc-dead" + run_dump_test "table-jump-gc-dead-symbol" + run_dump_test "table-jump-gc-comdat" + run_dump_test "table-jump-gc-comdat-symbol" + run_dump_test "table-jump-vma-lma" + # The following tests require shared library support. if ![check_shared_lib_support] { return } + run_dump_test "table-jump-pie" + run_dump_test "table-jump-pie-text" + run_dump_test "table-jump-pie-relocs" + run_dump_test "table-jump-shared" + run_dump_test "table-jump-shared-text" + run_dump_test "table-jump-shared-symbol" + run_dump_test "table-jump-shared-relocs" + run_dump_test "relro-relax-lui" run_dump_test "relro-relax-pcrel" run_dump_test "variant_cc-now" @@ -342,4 +391,5 @@ if [istarget "riscv*-*-*"] { run_dump_test "tls" run_dump_test "tlsbin" run_dump_test "absolute-no-relative" + } diff --git a/ld/testsuite/ld-riscv-elf/table-jump-addend.d b/ld/testsuite/ld-riscv-elf/table-jump-addend.d new file mode 100644 index 00000000000..11cc2b9fdfe --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-addend.d @@ -0,0 +1,18 @@ +#source: table-jump-addend.s +#as: -march=rv64ic_zcmt +#ld: -Ttable-jump.ld --relax-zcmt +#objdump: -d +#... +Disassembly of section .riscv.jvt: +0+[0-9a-f]+ <__jvt_base\$>: +[ ]+... +.*:[ ]+[0-9a-f]+[ ]+jvt.jalt\[32\]:[ ]+target +.*:[ ]+[0-9a-f]+[ ]+jvt.jalt\[33\]:[ ]+target_4 +.*:[ ]+[0-9a-f]+[ ]+jvt.jalt\[34\]:[ ]+target_8 +#... +Disassembly of section .text: +0+[0-9a-f]+ <_start>: +.*:[ ]+[0-9a-f]+[ ]+cm.jalt[ ]+32 # [0-9a-f]+ +.*:[ ]+[0-9a-f]+[ ]+cm.jalt[ ]+33 # [0-9a-f]+ +.*:[ ]+[0-9a-f]+[ ]+cm.jalt[ ]+34 # [0-9a-f]+ +#pass diff --git a/ld/testsuite/ld-riscv-elf/table-jump-addend.s b/ld/testsuite/ld-riscv-elf/table-jump-addend.s new file mode 100644 index 00000000000..823e0710e08 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-addend.s @@ -0,0 +1,21 @@ + .section .text + + .globl _start + .type _start, %function +_start: + .rept 50 + call target + call target + 4 + call target + 8 + .endr + + .globl target + .type target, %function +target: + .word 0x00000013 + .globl target_4 +target_4: + .word 0x00000013 + .globl target_8 +target_8: + ret diff --git a/ld/testsuite/ld-riscv-elf/table-jump-base-collision.d b/ld/testsuite/ld-riscv-elf/table-jump-base-collision.d new file mode 100644 index 00000000000..5cdfe8a8e77 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-base-collision.d @@ -0,0 +1,4 @@ +#source: table-jump-base-collision.s +#as: -march=rv64ic_zcmt +#ld: -Ttable-jump.ld --relax-zcmt +#error: .*__jvt_base\$ is reserved for Zcmt table-jump relaxation diff --git a/ld/testsuite/ld-riscv-elf/table-jump-base-collision.s b/ld/testsuite/ld-riscv-elf/table-jump-base-collision.s new file mode 100644 index 00000000000..182150f86a5 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-base-collision.s @@ -0,0 +1,18 @@ + .section .text + + .globl _start + .type _start, %function +_start: + .rept 5 + tail target + .endr + ret + .space 4096 + + .globl __jvt_base$ +__jvt_base$: + .word 0 + + .type target, %function +target: + ret diff --git a/ld/testsuite/ld-riscv-elf/table-jump-base-local-collision.d b/ld/testsuite/ld-riscv-elf/table-jump-base-local-collision.d new file mode 100644 index 00000000000..2708f2e86d1 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-base-local-collision.d @@ -0,0 +1,4 @@ +#source: table-jump-base-local-collision.s +#as: -march=rv64ic_zcmt +#ld: -Ttable-jump.ld --relax-zcmt +#error: .*__jvt_base\$ is reserved for Zcmt table-jump relaxation diff --git a/ld/testsuite/ld-riscv-elf/table-jump-base-local-collision.s b/ld/testsuite/ld-riscv-elf/table-jump-base-local-collision.s new file mode 100644 index 00000000000..f7206d15b49 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-base-local-collision.s @@ -0,0 +1,17 @@ + .section .text + + .globl _start + .type _start, %function +_start: + .rept 5 + tail target + .endr + ret + .space 4096 + +__jvt_base$: + .word 0 + + .type target, %function +target: + ret diff --git a/ld/testsuite/ld-riscv-elf/table-jump-be32-bytes.d b/ld/testsuite/ld-riscv-elf/table-jump-be32-bytes.d new file mode 100644 index 00000000000..49dc3451e16 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-be32-bytes.d @@ -0,0 +1,10 @@ +#source: table-jump-rv32.s +#as: -march=rv32ic_zcmt -mbig-endian +#ld: -melf32briscv -Ttable-jump.ld --relax-zcmt +#objdump: -s -j .riscv.jvt + +#... +.*: file format elf32-bigriscv +#... +Contents of section .riscv.jvt: +[ ]+0+[0-9a-f]*[ ]+0000400e[ ]+0000400c.* diff --git a/ld/testsuite/ld-riscv-elf/table-jump-be32-text.d b/ld/testsuite/ld-riscv-elf/table-jump-be32-text.d new file mode 100644 index 00000000000..a7a00bf3e39 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-be32-text.d @@ -0,0 +1,13 @@ +#source: table-jump-rv32.s +#as: -march=rv32ic_zcmt -mbig-endian +#ld: -melf32briscv -Ttable-jump.ld --relax-zcmt +#objdump: -d + +#... +.*: file format elf32-bigriscv +#... +Disassembly of section .text: +#... +.*:[ ]+[0-9a-f]+[ ]+cm.jt[ ]+0 # [0-9a-f]+ +.*:[ ]+[0-9a-f]+[ ]+cm.jt[ ]+1 # [0-9a-f]+ +#pass diff --git a/ld/testsuite/ld-riscv-elf/table-jump-be64-bytes.d b/ld/testsuite/ld-riscv-elf/table-jump-be64-bytes.d new file mode 100644 index 00000000000..7dbc2d1a30e --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-be64-bytes.d @@ -0,0 +1,10 @@ +#source: table-jump.s +#as: -march=rv64ic_zcmt --defsym TEST_CM_JT=1 -mbig-endian +#ld: -melf64briscv -Ttable-jump.ld --relax-zcmt +#objdump: -s -j .riscv.jvt + +#... +.*: file format elf64-bigriscv +#... +Contents of section .riscv.jvt: +[ ]+0+[0-9a-f]*[ ]+00000000[ ]+00004016[ ]+00000000[ ]+00004014.* diff --git a/ld/testsuite/ld-riscv-elf/table-jump-be64-text.d b/ld/testsuite/ld-riscv-elf/table-jump-be64-text.d new file mode 100644 index 00000000000..7477201f199 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-be64-text.d @@ -0,0 +1,13 @@ +#source: table-jump.s +#as: -march=rv64ic_zcmt --defsym TEST_CM_JT=1 -mbig-endian +#ld: -melf64briscv -Ttable-jump.ld --relax-zcmt +#objdump: -d + +#... +.*: file format elf64-bigriscv +#... +Disassembly of section .text: +#... +.*:[ ]+[0-9a-f]+[ ]+cm.jt[ ]+0 # [0-9a-f]+ +.*:[ ]+[0-9a-f]+[ ]+cm.jt[ ]+1 # [0-9a-f]+ +#pass diff --git a/ld/testsuite/ld-riscv-elf/table-jump-benefit.d b/ld/testsuite/ld-riscv-elf/table-jump-benefit.d new file mode 100644 index 00000000000..2fe5c787605 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-benefit.d @@ -0,0 +1,17 @@ +#source: table-jump-benefit.s +#as: -march=rv64ic_zcmt +#ld: -Ttable-jump.ld --relax-zcmt +#objdump: -d +#... +Disassembly of section .riscv.jvt: +0+[0-9a-f]+ <__jvt_base\$>: +[ ]+... +.*:[ ]+[0-9a-f]+[ ]+jvt.jalt\[32\]:[ ]+func_d +.*:[ ]+[0-9a-f]+[ ]+jvt.jalt\[33\]:[ ]+func_c +.*:[ ]+[0-9a-f]+[ ]+jvt.jalt\[34\]:[ ]+func_b +.*:[ ]+[0-9a-f]+[ ]+jvt.jalt\[35\]:[ ]+func_a +#... +Disassembly of section .text: +0+[0-9a-f]+ <_start>: +.*:[ ]+[0-9a-f]+[ ]+cm.jalt[ ]+32 # [0-9a-f]+ +#pass diff --git a/ld/testsuite/ld-riscv-elf/table-jump-benefit.s b/ld/testsuite/ld-riscv-elf/table-jump-benefit.s new file mode 100644 index 00000000000..0450fef000f --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-benefit.s @@ -0,0 +1,51 @@ + .section .text + + .globl _start + .type _start, %function +_start: + # Test benefit ranking: higher frequency functions should + # be prioritized for JVT entry allocation. + # Use reverse alphabetical order to verify sorting by benefit, + # not by name. + + # func_d called 80 times - highest benefit + .rept 80 + call func_d + .endr + + # func_c called 50 times - medium benefit + .rept 50 + call func_c + .endr + + # func_b called 20 times - lower benefit + .rept 20 + call func_b + .endr + + # func_a called 5 times - lowest benefit + .rept 5 + call func_a + .endr + + ret + + .globl func_a + .type func_a, %function +func_a: + ret + + .globl func_b + .type func_b, %function +func_b: + ret + + .globl func_c + .type func_c, %function +func_c: + ret + + .globl func_d + .type func_d, %function +func_d: + ret diff --git a/ld/testsuite/ld-riscv-elf/table-jump-default-jvt-relocs.d b/ld/testsuite/ld-riscv-elf/table-jump-default-jvt-relocs.d new file mode 100644 index 00000000000..9b3079f24b3 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-default-jvt-relocs.d @@ -0,0 +1,9 @@ +#source: table-jump.s +#as: -march=rv64ic_zcmt --defsym TEST_CM_JT_JALT=1 +#ld: --relax-zcmt +#readelf: -rW + +#failif +#... +.*R_RISCV_TABLE_JUMP.* +#pass diff --git a/ld/testsuite/ld-riscv-elf/table-jump-default-jvt-symbol.d b/ld/testsuite/ld-riscv-elf/table-jump-default-jvt-symbol.d new file mode 100644 index 00000000000..5dd5e43c680 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-default-jvt-symbol.d @@ -0,0 +1,10 @@ +#source: table-jump.s +#as: -march=rv64ic_zcmt --defsym TEST_CM_JT_JALT=1 +#ld: --relax-zcmt +#readelf: -SWs + +#... +.*\.riscv\.jvt[ ]+PROGBITS[ ]+[0-9a-f]+[ ]+[0-9a-f]+[ ]+[0-9a-f]+.* +#... +[ ]+[0-9]+:[ ]+0+[0-9a-f]+[ ]+0[ ]+NOTYPE[ ]+LOCAL[ ]+DEFAULT[ ]+[0-9]+[ ]+__jvt_base\$ +#pass diff --git a/ld/testsuite/ld-riscv-elf/table-jump-default-jvt.d b/ld/testsuite/ld-riscv-elf/table-jump-default-jvt.d new file mode 100644 index 00000000000..96c9efaa29d --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-default-jvt.d @@ -0,0 +1,12 @@ +#source: table-jump.s +#as: -march=rv64ic_zcmt --defsym TEST_CM_JT_JALT=1 +#ld: --relax-zcmt +#objdump: -d + +#... +Disassembly of section .text: +#... +.*:[ ]+[0-9a-f]+[ ]+cm.jt[ ]+0 # [0-9a-f]+ +#... +.*:[ ]+[0-9a-f]+[ ]+cm.jalt[ ]+32 # [0-9a-f]+ +#pass diff --git a/ld/testsuite/ld-riscv-elf/table-jump-default-no-jvt.d b/ld/testsuite/ld-riscv-elf/table-jump-default-no-jvt.d new file mode 100644 index 00000000000..1ebad80ec12 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-default-no-jvt.d @@ -0,0 +1,15 @@ +#source: table-jump-no-benefit.s +#as: -march=rv64ic_zcmt +#ld: --relax-zcmt +#objdump: -d + +#... +Disassembly of section .text: +#... +0+[0-9a-f]+ <_start>: +.*:[ ]+[0-9a-f]+[ ]+j[ ]+[0-9a-f]+ +.*:[ ]+[0-9a-f]+[ ]+j[ ]+[0-9a-f]+ +#... +0+[0-9a-f]+ : +.*:[ ]+[0-9a-f]+[ ]+ret +#pass diff --git a/ld/testsuite/ld-riscv-elf/table-jump-dump-unknown.d b/ld/testsuite/ld-riscv-elf/table-jump-dump-unknown.d new file mode 100644 index 00000000000..53e9097603c --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-dump-unknown.d @@ -0,0 +1,25 @@ +#source: table-jump.s +#as: -march=rv64ic_zcmt --defsym TEST_CM_JT=1 +#ld: -Ttable-jump.ld --strip-all --relax-zcmt +#objdump: -d +#... +Disassembly of section .riscv.jvt: +0+[0-9a-f]+ <.riscv.jvt>: +.*:[ ]+[0-9a-f]+[ ]+jvt.jt\[0\]:[ ]+ +.*:[ ]+[0-9a-f]+[ ]+jvt.jt\[1\]:[ ]+ +#... +Disassembly of section .text: +0+[0-9a-f]+ <.text>: +.*:[ ]+[0-9a-f]+[ ]+cm.jt[ ]+0 +.*:[ ]+[0-9a-f]+[ ]+cm.jt[ ]+1 +.*:[ ]+[0-9a-f]+[ ]+cm.jt[ ]+0 +.*:[ ]+[0-9a-f]+[ ]+cm.jt[ ]+1 +.*:[ ]+[0-9a-f]+[ ]+cm.jt[ ]+0 +.*:[ ]+[0-9a-f]+[ ]+cm.jt[ ]+1 +.*:[ ]+[0-9a-f]+[ ]+cm.jt[ ]+0 +.*:[ ]+[0-9a-f]+[ ]+cm.jt[ ]+1 +.*:[ ]+[0-9a-f]+[ ]+cm.jt[ ]+0 +.*:[ ]+[0-9a-f]+[ ]+cm.jt[ ]+1 +#... +.*:[ ]+[0-9a-f]+[ ]+ret +.*:[ ]+[0-9a-f]+[ ]+ret diff --git a/ld/testsuite/ld-riscv-elf/table-jump-emit-relocs.d b/ld/testsuite/ld-riscv-elf/table-jump-emit-relocs.d new file mode 100644 index 00000000000..32c69c727ae --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-emit-relocs.d @@ -0,0 +1,9 @@ +#source: table-jump.s +#as: -march=rv64ic_zcmt --defsym TEST_CM_JALT=1 +#ld: -Ttable-jump.ld --emit-relocs --relax-zcmt +#readelf: -rW + +#failif +#... +.*R_RISCV_(TABLE_JUMP|DELETE|DELETE_AND_RELAX).* +#pass diff --git a/ld/testsuite/ld-riscv-elf/table-jump-equal-benefit.d b/ld/testsuite/ld-riscv-elf/table-jump-equal-benefit.d new file mode 100644 index 00000000000..6f4ed2e2682 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-equal-benefit.d @@ -0,0 +1,18 @@ +#source: table-jump-equal-benefit.s +#as: -march=rv64ic_zcmt +#ld: -Ttable-jump.ld --relax-zcmt +#objdump: -d + +#... +Disassembly of section .riscv.jvt: +0+[0-9a-f]+ <__jvt_base\$>: +[ ]+... +.*:[ ]+[0-9a-f]+[ ]+jvt.jalt\[32\]:[ ]+func_b +.*:[ ]+[0-9a-f]+[ ]+jvt.jalt\[33\]:[ ]+func_a +#... +Disassembly of section .text: +#... +.*:[ ]+[0-9a-f]+[ ]+cm.jalt[ ]+32 # [0-9a-f]+ +#... +.*:[ ]+[0-9a-f]+[ ]+cm.jalt[ ]+33 # [0-9a-f]+ +#pass diff --git a/ld/testsuite/ld-riscv-elf/table-jump-equal-benefit.s b/ld/testsuite/ld-riscv-elf/table-jump-equal-benefit.s new file mode 100644 index 00000000000..13dc4200569 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-equal-benefit.s @@ -0,0 +1,19 @@ + .section .text + + .globl _start + .type _start, %function +_start: + .rept 70 + call func_b + call func_a + .endr + + .globl func_a + .type func_a, %function +func_a: + ret + + .globl func_b + .type func_b, %function +func_b: + ret diff --git a/ld/testsuite/ld-riscv-elf/table-jump-gc-comdat-symbol.d b/ld/testsuite/ld-riscv-elf/table-jump-gc-comdat-symbol.d new file mode 100644 index 00000000000..0b8ebee90bc --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-gc-comdat-symbol.d @@ -0,0 +1,9 @@ +#source: table-jump-gc-comdat.s +#as: -march=rv64ic_zcmt +#ld: --gc-sections --relax-zcmt -e _start +#readelf: -SWs + +#failif +#... +.*(__jvt_base\$|\.riscv\.jvt).* +#pass diff --git a/ld/testsuite/ld-riscv-elf/table-jump-gc-comdat.d b/ld/testsuite/ld-riscv-elf/table-jump-gc-comdat.d new file mode 100644 index 00000000000..6a5e01c8ae9 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-gc-comdat.d @@ -0,0 +1,11 @@ +#source: table-jump-gc-comdat.s +#as: -march=rv64ic_zcmt +#ld: --gc-sections --relax-zcmt -e _start +#objdump: -d + +#... +Disassembly of section .text: +#... +0+[0-9a-f]+ <_start>: +.*:[ ]+[0-9a-f]+[ ]+ret +#pass diff --git a/ld/testsuite/ld-riscv-elf/table-jump-gc-comdat.s b/ld/testsuite/ld-riscv-elf/table-jump-gc-comdat.s new file mode 100644 index 00000000000..591d7c47e29 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-gc-comdat.s @@ -0,0 +1,18 @@ + .section .text.live, "ax" + + .globl _start + .type _start, %function +_start: + ret + + .section .text.dead_group, "axG", @progbits, dead_group, comdat + .type dead_group_start, %function +dead_group_start: + .rept 70 + call dead_group_target + .endr + ret + + .type dead_group_target, %function +dead_group_target: + ret diff --git a/ld/testsuite/ld-riscv-elf/table-jump-gc-dead-symbol.d b/ld/testsuite/ld-riscv-elf/table-jump-gc-dead-symbol.d new file mode 100644 index 00000000000..b8a14241f12 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-gc-dead-symbol.d @@ -0,0 +1,9 @@ +#source: table-jump-gc-dead.s +#as: -march=rv64ic_zcmt +#ld: --gc-sections --relax-zcmt -e _start +#readelf: -SWs + +#failif +#... +.*(__jvt_base\$|\.riscv\.jvt).* +#pass diff --git a/ld/testsuite/ld-riscv-elf/table-jump-gc-dead.d b/ld/testsuite/ld-riscv-elf/table-jump-gc-dead.d new file mode 100644 index 00000000000..1c95f06c7e0 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-gc-dead.d @@ -0,0 +1,11 @@ +#source: table-jump-gc-dead.s +#as: -march=rv64ic_zcmt +#ld: --gc-sections --relax-zcmt -e _start +#objdump: -d + +#... +Disassembly of section .text: +#... +0+[0-9a-f]+ <_start>: +.*:[ ]+[0-9a-f]+[ ]+ret +#pass diff --git a/ld/testsuite/ld-riscv-elf/table-jump-gc-dead.s b/ld/testsuite/ld-riscv-elf/table-jump-gc-dead.s new file mode 100644 index 00000000000..0030a207897 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-gc-dead.s @@ -0,0 +1,18 @@ + .section .text.live, "ax" + + .globl _start + .type _start, %function +_start: + ret + + .section .text.dead, "ax" + .type dead_start, %function +dead_start: + .rept 70 + call dead_target + .endr + ret + + .type dead_target, %function +dead_target: + ret diff --git a/ld/testsuite/ld-riscv-elf/table-jump-jalt.d b/ld/testsuite/ld-riscv-elf/table-jump-jalt.d new file mode 100644 index 00000000000..098e65fc403 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-jalt.d @@ -0,0 +1,18 @@ +#source: table-jump.s +#as: -march=rv64ic_zcmt --defsym TEST_CM_JALT=1 +#ld: -Ttable-jump.ld --relax-zcmt +#objdump: -d +#... +Disassembly of section .riscv.jvt: +0+[0-9a-f]+ <__jvt_base\$>: +[ ]+... +.*:[ ]+[0-9a-f]+[ ]+jvt.jalt\[32\]:[ ]+foo_global +.*:[ ]+[0-9a-f]+[ ]+jvt.jalt\[33\]:[ ]+foo_local +#... +Disassembly of section .text: +0+[0-9a-f]+ <_start>: +.*:[ ]+[0-9a-f]+[ ]+cm.jalt[ ]+32 # [0-9a-f]+ +.*:[ ]+[0-9a-f]+[ ]+cm.jalt[ ]+33 # [0-9a-f]+ +.*:[ ]+[0-9a-f]+[ ]+cm.jalt[ ]+32 # [0-9a-f]+ +.*:[ ]+[0-9a-f]+[ ]+cm.jalt[ ]+33 # [0-9a-f]+ +#... diff --git a/ld/testsuite/ld-riscv-elf/table-jump-jt.d b/ld/testsuite/ld-riscv-elf/table-jump-jt.d new file mode 100644 index 00000000000..0b0250ee104 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-jt.d @@ -0,0 +1,23 @@ +#source: table-jump.s +#as: -march=rv64ic_zcmt --defsym TEST_CM_JT=1 +#ld: -Ttable-jump.ld --relax-zcmt +#objdump: -d +#... +Disassembly of section .riscv.jvt: +0+[0-9a-f]+ <__jvt_base\$>: +.*:[ ]+[0-9a-f]+[ ]+jvt.jt\[0\]:[ ]+foo_local +.*:[ ]+[0-9a-f]+[ ]+jvt.jt\[1\]:[ ]+foo_global +#... +Disassembly of section .text: +0+[0-9a-f]+ <_start>: +.*:[ ]+[0-9a-f]+[ ]+cm.jt[ ]+0 # [0-9a-f]+ +.*:[ ]+[0-9a-f]+[ ]+cm.jt[ ]+1 # [0-9a-f]+ +.*:[ ]+[0-9a-f]+[ ]+cm.jt[ ]+0 # [0-9a-f]+ +.*:[ ]+[0-9a-f]+[ ]+cm.jt[ ]+1 # [0-9a-f]+ +.*:[ ]+[0-9a-f]+[ ]+cm.jt[ ]+0 # [0-9a-f]+ +.*:[ ]+[0-9a-f]+[ ]+cm.jt[ ]+1 # [0-9a-f]+ +.*:[ ]+[0-9a-f]+[ ]+cm.jt[ ]+0 # [0-9a-f]+ +.*:[ ]+[0-9a-f]+[ ]+cm.jt[ ]+1 # [0-9a-f]+ +.*:[ ]+[0-9a-f]+[ ]+cm.jt[ ]+0 # [0-9a-f]+ +.*:[ ]+[0-9a-f]+[ ]+cm.jt[ ]+1 # [0-9a-f]+ +#... diff --git a/ld/testsuite/ld-riscv-elf/table-jump-multiple-local-sym-2.s b/ld/testsuite/ld-riscv-elf/table-jump-multiple-local-sym-2.s new file mode 100644 index 00000000000..bf106b88f2d --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-multiple-local-sym-2.s @@ -0,0 +1,12 @@ + .section .text + .type bar, %function +bar: + .rept 70 + call foo_local + call foo_global + .endr + ret + + .type foo_local, %function +foo_local: + ret diff --git a/ld/testsuite/ld-riscv-elf/table-jump-multiple-local-sym.d b/ld/testsuite/ld-riscv-elf/table-jump-multiple-local-sym.d new file mode 100644 index 00000000000..07dbd3978be --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-multiple-local-sym.d @@ -0,0 +1,16 @@ +#source: table-jump-multiple-local-sym.s +#source: table-jump-multiple-local-sym-2.s +#as: -march=rv64ic_zcmt +#ld: -Ttable-jump.ld --relax-zcmt +#objdump: -d + +#... +Disassembly of section .riscv.jvt: +0+[0-9a-f]+ <__jvt_base\$>: +[ ]+... +.*:[ ]+[0-9a-f]+[ ]+jvt.jalt\[32\]:[ ]+foo_global +.*:[ ]+[0-9a-f]+[ ]+jvt.jalt\[33\]:[ ]+foo_local +.*:[ ]+[0-9a-f]+[ ]+jvt.jalt\[34\]:[ ]+foo_local + +Disassembly of section .text: +#... diff --git a/ld/testsuite/ld-riscv-elf/table-jump-multiple-local-sym.s b/ld/testsuite/ld-riscv-elf/table-jump-multiple-local-sym.s new file mode 100644 index 00000000000..ccc2525e2f7 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-multiple-local-sym.s @@ -0,0 +1,18 @@ + .section .text + + .globl _start + .type _start, %function +_start: + .rept 70 + call foo_global + call foo_local + .endr + + .globl foo_global + .type foo_global, %function +foo_global: + ret + + .type foo_local, %function +foo_local: + ret diff --git a/ld/testsuite/ld-riscv-elf/table-jump-no-benefit-jvt-ref.d b/ld/testsuite/ld-riscv-elf/table-jump-no-benefit-jvt-ref.d new file mode 100644 index 00000000000..3b392efa45c --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-no-benefit-jvt-ref.d @@ -0,0 +1,4 @@ +#source: table-jump-no-benefit-jvt-ref.s +#as: -march=rv64ic_zcmt +#ld: --relax-zcmt +#error: .*undefined reference to `__jvt_base\$' diff --git a/ld/testsuite/ld-riscv-elf/table-jump-no-benefit-jvt-ref.s b/ld/testsuite/ld-riscv-elf/table-jump-no-benefit-jvt-ref.s new file mode 100644 index 00000000000..3665215f92d --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-no-benefit-jvt-ref.s @@ -0,0 +1,16 @@ + .section .text + + .globl _start + .type _start, %function +_start: + .option push + .option norelax + la a0, __jvt_base$ + .option pop + tail target + tail target + .space 4096 + + .type target, %function +target: + ret diff --git a/ld/testsuite/ld-riscv-elf/table-jump-no-benefit-section.d b/ld/testsuite/ld-riscv-elf/table-jump-no-benefit-section.d new file mode 100644 index 00000000000..74363ad11c6 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-no-benefit-section.d @@ -0,0 +1,9 @@ +#source: table-jump-no-benefit.s +#as: -march=rv64ic_zcmt +#ld: --relax-zcmt +#readelf: -SW + +#failif +#... +.*\.riscv\.jvt.* +#pass diff --git a/ld/testsuite/ld-riscv-elf/table-jump-no-benefit-symbol.d b/ld/testsuite/ld-riscv-elf/table-jump-no-benefit-symbol.d new file mode 100644 index 00000000000..6d5eb9a35b0 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-no-benefit-symbol.d @@ -0,0 +1,9 @@ +#source: table-jump-no-benefit.s +#as: -march=rv64ic_zcmt +#ld: --relax-zcmt +#readelf: -sW + +#failif +#... +.*__jvt_base\$.* +#pass diff --git a/ld/testsuite/ld-riscv-elf/table-jump-no-benefit.s b/ld/testsuite/ld-riscv-elf/table-jump-no-benefit.s new file mode 100644 index 00000000000..2292cc43b3e --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-no-benefit.s @@ -0,0 +1,12 @@ + .section .text + + .globl _start + .type _start, %function +_start: + tail target + tail target + .space 4096 + + .type target, %function +target: + ret diff --git a/ld/testsuite/ld-riscv-elf/table-jump-no-relax-zcmt.d b/ld/testsuite/ld-riscv-elf/table-jump-no-relax-zcmt.d new file mode 100644 index 00000000000..a551a05c97e --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-no-relax-zcmt.d @@ -0,0 +1,17 @@ +#source: table-jump.s +#as: -march=rv64ic_zcmt --defsym TEST_CM_JT_JALT=1 +#ld: -Ttable-jump.ld --no-relax-zcmt +#objdump: -d +#... +Disassembly of section .text: +0+[0-9a-f]+ <_start>: +.*:[ ]+[0-9a-f]+[ ]+j[ ]+[0-9a-f]+ +.*:[ ]+[0-9a-f]+[ ]+j[ ]+[0-9a-f]+ +.*:[ ]+[0-9a-f]+[ ]+j[ ]+[0-9a-f]+ +.*:[ ]+[0-9a-f]+[ ]+j[ ]+[0-9a-f]+ +.*:[ ]+[0-9a-f]+[ ]+j[ ]+[0-9a-f]+ +.*:[ ]+[0-9a-f]+[ ]+jal[ ]+[0-9a-f]+ +.*:[ ]+[0-9a-f]+[ ]+jal[ ]+[0-9a-f]+ +.*:[ ]+[0-9a-f]+[ ]+jal[ ]+[0-9a-f]+ +.*:[ ]+[0-9a-f]+[ ]+jal[ ]+[0-9a-f]+ +#... diff --git a/ld/testsuite/ld-riscv-elf/table-jump-no-relo-1.s b/ld/testsuite/ld-riscv-elf/table-jump-no-relo-1.s new file mode 100644 index 00000000000..d3e9b7ce4dd --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-no-relo-1.s @@ -0,0 +1,7 @@ + .section .text + + .globl _start + .type _start, %function +_start: +L0: j L0 + ret diff --git a/ld/testsuite/ld-riscv-elf/table-jump-no-relo-2.s b/ld/testsuite/ld-riscv-elf/table-jump-no-relo-2.s new file mode 100644 index 00000000000..f68cdaf423b --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-no-relo-2.s @@ -0,0 +1,12 @@ + .section .text + + .globl foo + .type foo, %function +foo: + call bar + + + .globl bar + .type bar, %function +bar: + ret diff --git a/ld/testsuite/ld-riscv-elf/table-jump-no-relo.d b/ld/testsuite/ld-riscv-elf/table-jump-no-relo.d new file mode 100644 index 00000000000..9ff45cb2616 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-no-relo.d @@ -0,0 +1,16 @@ +#source: table-jump-no-relo-1.s +#source: table-jump-no-relo-2.s +#as: -march=rv64ic_zcmt +#ld: -Ttable-jump.ld --relax-zcmt +#objdump: -d +#... +Disassembly of section .text: +0+[0-9a-f]+ <_start>: +.*:[ ]+[0-9a-f]+[ ]+j[ ]+[0-9a-f]+ <_start> +.*:[ ]+[0-9a-f]+[ ]+ret + +0+[0-9a-f]+ : +.*:[ ]+[0-9a-f]+[ ]+jal[ ]+[0-9a-f]+ + +0+[0-9a-f]+ : +.*:[ ]+[0-9a-f]+[ ]+ret diff --git a/ld/testsuite/ld-riscv-elf/table-jump-no-zcmt.d b/ld/testsuite/ld-riscv-elf/table-jump-no-zcmt.d new file mode 100644 index 00000000000..5b23e81e2c8 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-no-zcmt.d @@ -0,0 +1,16 @@ +#source: table-jump-no-zcmt.s +#as: -march=rv64ic +#ld: -Ttable-jump.ld --relax-zcmt +#objdump: -d +#... +Disassembly of section .text: +0+[0-9a-f]+ <_start>: +# All calls should remain as jal (not converted to cm.jalt) +.*:[ ]+[0-9a-f]+[ ]+jal[ ]+[0-9a-f]+ +.*:[ ]+[0-9a-f]+[ ]+jal[ ]+[0-9a-f]+ +.*:[ ]+[0-9a-f]+[ ]+jal[ ]+[0-9a-f]+ +.*:[ ]+[0-9a-f]+[ ]+jal[ ]+[0-9a-f]+ +#... +0+[0-9a-f]+ : +.*:[ ]+[0-9a-f]+[ ]+ret +#pass diff --git a/ld/testsuite/ld-riscv-elf/table-jump-no-zcmt.s b/ld/testsuite/ld-riscv-elf/table-jump-no-zcmt.s new file mode 100644 index 00000000000..3e483757ba5 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-no-zcmt.s @@ -0,0 +1,16 @@ + .section .text + + .globl _start + .type _start, %function +_start: + # This file is assembled without Zcmt extension. + # The linker should NOT generate JVT section + .rept 50 + call foo + .endr + ret + + .globl foo + .type foo, %function +foo: + ret diff --git a/ld/testsuite/ld-riscv-elf/table-jump-norelax.d b/ld/testsuite/ld-riscv-elf/table-jump-norelax.d new file mode 100644 index 00000000000..8621ad8550b --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-norelax.d @@ -0,0 +1,15 @@ +#source: table-jump-norelax.s +#as: -march=rv64ic_zcmt +#ld: -Ttable-jump.ld --relax-zcmt +#objdump: -d +#... +Disassembly of section .text: +0+[0-9a-f]+ <_start>: +.*:[ ]+[0-9a-f]+[ ]+auipc[ ]+ra,0x1 +.*:[ ]+[0-9a-f]+[ ]+jalr[ ]+[0-9]+\(ra\) # [0-9a-f]+ +.*:[ ]+[0-9a-f]+[ ]+auipc[ ]+t[0-9],0x1 +.*:[ ]+[0-9a-f]+[ ]+jr[ ]+[0-9]+\(t[0-9]\) # [0-9a-f]+ +.*:[ ]+[0-9a-f]+[ ]+j[ ]+[0-9a-f]+ +#... +0+[0-9a-f]+ : +.*:[ ]+[0-9a-f]+[ ]+ret diff --git a/ld/testsuite/ld-riscv-elf/table-jump-norelax.s b/ld/testsuite/ld-riscv-elf/table-jump-norelax.s new file mode 100644 index 00000000000..0880f79a5c5 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-norelax.s @@ -0,0 +1,17 @@ + .section .text + + .globl _start + .type _start, %function +_start: + .option push + .option norelax + call target + tail target + jal x0, target + .option pop + + .space 4096 + + .type target, %function +target: + ret diff --git a/ld/testsuite/ld-riscv-elf/table-jump-overflow.d b/ld/testsuite/ld-riscv-elf/table-jump-overflow.d new file mode 100644 index 00000000000..4b5e36005a9 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-overflow.d @@ -0,0 +1,11 @@ +#source: table-jump-overflow.s +#as: -march=rv64ic_zcmt +#ld: -Ttable-jump.ld --relax-zcmt +#objdump: -d +#... +Disassembly of section .text: +0+[0-9a-f]+ <_start>: +.*:[ ]+[0-9a-f]+[ ]+jal[ ]+[0-9a-f]+ +#... +.*:[ ]+[0-9a-f]+[ ]+jal[ ]+[0-9a-f]+ +#pass diff --git a/ld/testsuite/ld-riscv-elf/table-jump-overflow.s b/ld/testsuite/ld-riscv-elf/table-jump-overflow.s new file mode 100644 index 00000000000..5aae80f24c6 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-overflow.s @@ -0,0 +1,49 @@ + .altmacro + .section .text + + # Test JVT overflow: cm.jalt has 224 entries (index 32-255) + # func_top: called 10x (highest benefit), guaranteed jvt.jalt[32] + # func_0 to func_222: called 2x each, fill remaining 223 JVT slots + # func_overflow: called 1x (lowest benefit), overflows, remains jal + + .macro call2 n + call func_\n + call func_\n + .endm + + .macro defn n + .type func_\n, %function +func_\n: ret + .endm + + .globl _start + .type _start, %function +_start: + # func_top: highest benefit, guaranteed first JVT entry + .rept 10 + call func_top + .endr + + # 223 functions with 2 calls each (fill remaining JVT entries) + .set i, 0 + .rept 223 + call2 %i + .set i, i+1 + .endr + + # func_overflow: lowest benefit, will not fit in JVT + call func_overflow + ret + + # Define functions + .type func_top, %function +func_top: ret + + .set i, 0 + .rept 223 + defn %i + .set i, i+1 + .endr + + .type func_overflow, %function +func_overflow: ret diff --git a/ld/testsuite/ld-riscv-elf/table-jump-pie-relocs.d b/ld/testsuite/ld-riscv-elf/table-jump-pie-relocs.d new file mode 100644 index 00000000000..407acf5fcc6 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-pie-relocs.d @@ -0,0 +1,9 @@ +#source: table-jump-pie.s +#as: -march=rv64ic_zcmt -fpic +#ld: -pie --relax-zcmt +#readelf: -rW + +#failif +#... +.*R_RISCV_(TABLE_JUMP|DELETE|DELETE_AND_RELAX).* +#pass diff --git a/ld/testsuite/ld-riscv-elf/table-jump-pie-text.d b/ld/testsuite/ld-riscv-elf/table-jump-pie-text.d new file mode 100644 index 00000000000..8cb52d4a5df --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-pie-text.d @@ -0,0 +1,9 @@ +#source: table-jump-pie.s +#as: -march=rv64ic_zcmt -fpic +#ld: -pie --relax-zcmt +#objdump: -d + +#failif +#... +.*cm\.j(al)?t.* +#pass diff --git a/ld/testsuite/ld-riscv-elf/table-jump-pie.d b/ld/testsuite/ld-riscv-elf/table-jump-pie.d new file mode 100644 index 00000000000..d8a8a6a532d --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-pie.d @@ -0,0 +1,9 @@ +#source: table-jump-pie.s +#as: -march=rv64ic_zcmt -fpic +#ld: -pie --relax-zcmt +#readelf: -SWs + +#failif +#... +.*(__jvt_base\$|\.riscv\.jvt).* +#pass diff --git a/ld/testsuite/ld-riscv-elf/table-jump-pie.s b/ld/testsuite/ld-riscv-elf/table-jump-pie.s new file mode 100644 index 00000000000..3d5fe7759bd --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-pie.s @@ -0,0 +1,13 @@ + .section .text + + .globl _start + .type _start, %function +_start: + .rept 70 + call target + .endr + ret + + .type target, %function +target: + ret diff --git a/ld/testsuite/ld-riscv-elf/table-jump-relax-zcmt.d b/ld/testsuite/ld-riscv-elf/table-jump-relax-zcmt.d new file mode 100644 index 00000000000..1adb1b289ce --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-relax-zcmt.d @@ -0,0 +1,23 @@ +#source: table-jump.s +#as: -march=rv64ic_zcmt --defsym TEST_CM_JT_JALT=1 +#ld: -Ttable-jump.ld --relax-zcmt +#objdump: -d +#... +Disassembly of section .riscv.jvt: +0+[0-9a-f]+ <__jvt_base\$>: +.*:[ ]+[0-9a-f]+[ ]+jvt.jt\[0\]:[ ]+foo_global +[ ]+... +.*:[ ]+[0-9a-f]+[ ]+jvt.jalt\[32\]:[ ]+foo_global +#... +Disassembly of section .text: +0+[0-9a-f]+ <_start>: +.*:[ ]+[0-9a-f]+[ ]+cm.jt[ ]+0 # [0-9a-f]+ +.*:[ ]+[0-9a-f]+[ ]+cm.jt[ ]+0 # [0-9a-f]+ +.*:[ ]+[0-9a-f]+[ ]+cm.jt[ ]+0 # [0-9a-f]+ +.*:[ ]+[0-9a-f]+[ ]+cm.jt[ ]+0 # [0-9a-f]+ +.*:[ ]+[0-9a-f]+[ ]+cm.jt[ ]+0 # [0-9a-f]+ +.*:[ ]+[0-9a-f]+[ ]+cm.jalt[ ]+32 # [0-9a-f]+ +.*:[ ]+[0-9a-f]+[ ]+cm.jalt[ ]+32 # [0-9a-f]+ +.*:[ ]+[0-9a-f]+[ ]+cm.jalt[ ]+32 # [0-9a-f]+ +.*:[ ]+[0-9a-f]+[ ]+cm.jalt[ ]+32 # [0-9a-f]+ +#... diff --git a/ld/testsuite/ld-riscv-elf/table-jump-rv32.d b/ld/testsuite/ld-riscv-elf/table-jump-rv32.d new file mode 100644 index 00000000000..ef6bbcdd526 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-rv32.d @@ -0,0 +1,15 @@ +#source: table-jump-rv32.s +#as: -march=rv32ic_zcmt +#ld: -Ttable-jump.ld --relax-zcmt -melf32lriscv +#objdump: -d +#... +Disassembly of section .riscv.jvt: +0+[0-9a-f]+ <__jvt_base\$>: +.*:[ ]+[0-9a-f]+[ ]+jvt.jt\[0\]:[ ]+foo_local +.*:[ ]+[0-9a-f]+[ ]+jvt.jt\[1\]:[ ]+foo_global +#... +Disassembly of section .text: +0+[0-9a-f]+ <_start>: +.*:[ ]+[0-9a-f]+[ ]+cm.jt[ ]+0 # [0-9a-f]+ +.*:[ ]+[0-9a-f]+[ ]+cm.jt[ ]+1 # [0-9a-f]+ +#pass diff --git a/ld/testsuite/ld-riscv-elf/table-jump-rv32.s b/ld/testsuite/ld-riscv-elf/table-jump-rv32.s new file mode 100644 index 00000000000..274c3b03f8b --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-rv32.s @@ -0,0 +1,25 @@ + .section .text + + # Test RV32 ZCMT relaxation for cm.jt + # jal x0 (no link) -> cm.jt (index 0-31) + # JVT entry cost: 4 bytes (RV32), benefit = 2 per call + # Threshold: 3*2=6 > 4 (just profitable) + + .globl _start + .type _start, %function +_start: + .rept 3 + tail foo_local + tail foo_global + .endr + + .space 4096 + + .globl foo_global + .type foo_global, %function +foo_global: + ret + + .type foo_local, %function +foo_local: + ret diff --git a/ld/testsuite/ld-riscv-elf/table-jump-shared-relocs.d b/ld/testsuite/ld-riscv-elf/table-jump-shared-relocs.d new file mode 100644 index 00000000000..1c879fff883 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-shared-relocs.d @@ -0,0 +1,9 @@ +#source: table-jump-shared.s +#as: -march=rv64ic_zcmt -fpic +#ld: -shared --relax-zcmt +#readelf: -rW + +#failif +#... +.*R_RISCV_(TABLE_JUMP|DELETE|DELETE_AND_RELAX).* +#pass diff --git a/ld/testsuite/ld-riscv-elf/table-jump-shared-symbol.d b/ld/testsuite/ld-riscv-elf/table-jump-shared-symbol.d new file mode 100644 index 00000000000..a82763c2f8c --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-shared-symbol.d @@ -0,0 +1,9 @@ +#source: table-jump-shared.s +#as: -march=rv64ic_zcmt -fpic +#ld: -shared --relax-zcmt +#readelf: -SWs + +#failif +#... +.*(__jvt_base\$|\.riscv\.jvt).* +#pass diff --git a/ld/testsuite/ld-riscv-elf/table-jump-shared-text.d b/ld/testsuite/ld-riscv-elf/table-jump-shared-text.d new file mode 100644 index 00000000000..262d4c59643 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-shared-text.d @@ -0,0 +1,9 @@ +#source: table-jump-shared.s +#as: -march=rv64ic_zcmt -fpic +#ld: -shared --relax-zcmt +#objdump: -d + +#failif +#... +.*cm\.j(al)?t.* +#pass diff --git a/ld/testsuite/ld-riscv-elf/table-jump-shared.d b/ld/testsuite/ld-riscv-elf/table-jump-shared.d new file mode 100644 index 00000000000..1fec141e6b6 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-shared.d @@ -0,0 +1,12 @@ +#source: table-jump-shared.s +#as: -march=rv64ic_zcmt -fpic +#ld: -shared --relax-zcmt +#objdump: -d +#... +Disassembly of section .text: +#... +0+[0-9a-f]+ : +# Calls should NOT be cm.jalt in shared library (should be jal to PLT) +.*:[ ]+[0-9a-f]+[ ]+jal[ ]+[0-9a-f]+ +.*:[ ]+[0-9a-f]+[ ]+jal[ ]+[0-9a-f]+ +#pass diff --git a/ld/testsuite/ld-riscv-elf/table-jump-shared.s b/ld/testsuite/ld-riscv-elf/table-jump-shared.s new file mode 100644 index 00000000000..0bd853d1ae6 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-shared.s @@ -0,0 +1,15 @@ + .section .text + + .globl foo + .type foo, %function +foo: + # Shared library: JVT relaxation should be disabled + .rept 50 + call bar + .endr + ret + + .globl bar + .type bar, %function +bar: + ret diff --git a/ld/testsuite/ld-riscv-elf/table-jump-strip-symbol.d b/ld/testsuite/ld-riscv-elf/table-jump-strip-symbol.d new file mode 100644 index 00000000000..39b1d99e93e --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-strip-symbol.d @@ -0,0 +1,9 @@ +#source: table-jump.s +#as: -march=rv64ic_zcmt --defsym TEST_CM_JALT=1 +#ld: -Ttable-jump.ld --strip-all --relax-zcmt +#readelf: -sW + +#failif +#... +.*__jvt_base\$.* +#pass diff --git a/ld/testsuite/ld-riscv-elf/table-jump-symbol-policy.d b/ld/testsuite/ld-riscv-elf/table-jump-symbol-policy.d new file mode 100644 index 00000000000..acd152a93be --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-symbol-policy.d @@ -0,0 +1,8 @@ +#source: table-jump.s +#as: -march=rv64ic_zcmt --defsym TEST_CM_JALT=1 +#ld: -Ttable-jump.ld --relax-zcmt +#readelf: -sW + +#... +[ ]+[0-9]+:[ ]+0+[0-9a-f]+[ ]+0[ ]+NOTYPE[ ]+LOCAL[ ]+DEFAULT[ ]+[0-9]+[ ]+__jvt_base\$ +#pass diff --git a/ld/testsuite/ld-riscv-elf/table-jump-vma-lma.d b/ld/testsuite/ld-riscv-elf/table-jump-vma-lma.d new file mode 100644 index 00000000000..222d546df8b --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-vma-lma.d @@ -0,0 +1,16 @@ +#source: table-jump.s +#as: -march=rv64ic_zcmt --defsym TEST_CM_JALT=1 +#ld: -Ttable-jump-vma-lma.ld --relax-zcmt +#objdump: -d + +#... +Disassembly of section .riscv.jvt: +#... +.*:[ ]+0000000000003118[ ]+jvt.jalt\[32\]:[ ]+foo_global +.*:[ ]+000000000000311a[ ]+jvt.jalt\[33\]:[ ]+foo_local +#... +Disassembly of section .text: +#... +.*:[ ]+[0-9a-f]+[ ]+cm.jalt[ ]+32 # 3118 +.*:[ ]+[0-9a-f]+[ ]+cm.jalt[ ]+33 # 311a +#pass diff --git a/ld/testsuite/ld-riscv-elf/table-jump-vma-lma.ld b/ld/testsuite/ld-riscv-elf/table-jump-vma-lma.ld new file mode 100644 index 00000000000..a8202afb381 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-vma-lma.ld @@ -0,0 +1,10 @@ +ENTRY(_start) +SECTIONS +{ + .riscv.jvt 0x1000 : AT(0x8000) { + *(.riscv.jvt) + } + .text 0x3000 : AT(0x9000) { + *(.text) + } +} diff --git a/ld/testsuite/ld-riscv-elf/table-jump-vma-zero.d b/ld/testsuite/ld-riscv-elf/table-jump-vma-zero.d new file mode 100644 index 00000000000..c93a1c6c4f2 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-vma-zero.d @@ -0,0 +1,15 @@ +#source: table-jump-vma-zero.s +#as: -march=rv64ic_zcmt +#ld: -Ttable-jump-vma-zero.ld --relax-zcmt +#objdump: -d -s -j .riscv.jvt -j .text + +#... +Contents of section .riscv.jvt: +[ ]+1000[ ]+00000000[ ]+00000000.* +#... +Disassembly of section .text: +#... +0+3000 <_start>: +.*:[ ]+[0-9a-f]+[ ]+cm.jt[ ]+0 # 0 +.*:[ ]+[0-9a-f]+[ ]+cm.jt[ ]+0 # 0 +#pass diff --git a/ld/testsuite/ld-riscv-elf/table-jump-vma-zero.ld b/ld/testsuite/ld-riscv-elf/table-jump-vma-zero.ld new file mode 100644 index 00000000000..6db8ac52006 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-vma-zero.ld @@ -0,0 +1,13 @@ +ENTRY(_start) +SECTIONS +{ + .text.target 0x0 : { + *(.text.target) + } + .riscv.jvt 0x1000 : { + *(.riscv.jvt) + } + .text 0x3000 : { + *(.text.start) + } +} diff --git a/ld/testsuite/ld-riscv-elf/table-jump-vma-zero.s b/ld/testsuite/ld-riscv-elf/table-jump-vma-zero.s new file mode 100644 index 00000000000..742a0ee23fe --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-vma-zero.s @@ -0,0 +1,14 @@ + .section .text.start, "ax" + + .globl _start + .type _start, %function +_start: + .rept 5 + tail target + .endr + ret + + .section .text.target, "ax" + .type target, %function +target: + ret diff --git a/ld/testsuite/ld-riscv-elf/table-jump-zcd-conflict.d b/ld/testsuite/ld-riscv-elf/table-jump-zcd-conflict.d new file mode 100644 index 00000000000..ed70f3fd94e --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-zcd-conflict.d @@ -0,0 +1,9 @@ +#source: table-jump.s +#as: -march=rv64imafd_zicsr_zifencei_zca_zcd_zcmt --defsym TEST_CM_JT_JALT=1 +#ld: -Ttable-jump.ld --relax-zcmt +#readelf: -SWs + +#failif +#... +.*(__jvt_base\$|\.riscv\.jvt).* +#pass diff --git a/ld/testsuite/ld-riscv-elf/table-jump-zcmt-no-zca.d b/ld/testsuite/ld-riscv-elf/table-jump-zcmt-no-zca.d new file mode 100644 index 00000000000..9554df1aa91 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-zcmt-no-zca.d @@ -0,0 +1,9 @@ +#source: table-jump-zcmt-no-zca.s +#as: -march=rv64i -mno-arch-attr +#ld: --relax-zcmt +#readelf: -SWs + +#failif +#... +.*(__jvt_base\$|\.riscv\.jvt).* +#pass diff --git a/ld/testsuite/ld-riscv-elf/table-jump-zcmt-no-zca.s b/ld/testsuite/ld-riscv-elf/table-jump-zcmt-no-zca.s new file mode 100644 index 00000000000..91aa8f07ed3 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-zcmt-no-zca.s @@ -0,0 +1,24 @@ + .section .riscv.attributes,"",@0x70000003 + .byte 0x41 +0: + .4byte 1f-0b + .asciz "riscv" +2: + .byte 1 + .4byte 1f-2b + .byte 5 + .asciz "rv64i2p1_zicsr2p0_zcmt1p0" +1: + + .section .text + .globl _start + .type _start, %function +_start: + .rept 70 + call target + .endr + ret + + .type target, %function +target: + ret diff --git a/ld/testsuite/ld-riscv-elf/table-jump-zcmt-no-zicsr.d b/ld/testsuite/ld-riscv-elf/table-jump-zcmt-no-zicsr.d new file mode 100644 index 00000000000..981e5933097 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-zcmt-no-zicsr.d @@ -0,0 +1,9 @@ +#source: table-jump-zcmt-no-zicsr.s +#as: -march=rv64i -mno-arch-attr +#ld: --relax-zcmt +#readelf: -SWs + +#failif +#... +.*(__jvt_base\$|\.riscv\.jvt).* +#pass diff --git a/ld/testsuite/ld-riscv-elf/table-jump-zcmt-no-zicsr.s b/ld/testsuite/ld-riscv-elf/table-jump-zcmt-no-zicsr.s new file mode 100644 index 00000000000..768a6fb32fa --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump-zcmt-no-zicsr.s @@ -0,0 +1,24 @@ + .section .riscv.attributes,"",@0x70000003 + .byte 0x41 +0: + .4byte 1f-0b + .asciz "riscv" +2: + .byte 1 + .4byte 1f-2b + .byte 5 + .asciz "rv64i2p1_zca1p0_zcmt1p0" +1: + + .section .text + .globl _start + .type _start, %function +_start: + .rept 70 + call target + .endr + ret + + .type target, %function +target: + ret diff --git a/ld/testsuite/ld-riscv-elf/table-jump.ld b/ld/testsuite/ld-riscv-elf/table-jump.ld new file mode 100644 index 00000000000..ab84fdcb772 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump.ld @@ -0,0 +1,16 @@ +ENTRY(_start) +SECTIONS +{ + .got 0x1000 : { + *(.got) + } + .riscv.jvt : { + *(.riscv.jvt) + } + .data 0x2000: { + *(.data) + } + .text 0x3000 : { + *(.text) + } +} diff --git a/ld/testsuite/ld-riscv-elf/table-jump.s b/ld/testsuite/ld-riscv-elf/table-jump.s new file mode 100644 index 00000000000..75574a69223 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/table-jump.s @@ -0,0 +1,46 @@ + .section .text + + .globl _start + .type _start, %function +_start: +.ifdef TEST_CM_JT + .rept 5 + tail foo_local + tail foo_global + .endr +.endif + +.ifdef TEST_CM_JALT + .rept 70 + call foo_global + call foo_local + .endr +.endif + +.ifdef TEST_CM_JT_JALT + .rept 5 + tail foo_global + .endr + .rept 140 + call foo_global + .endr +.endif + + # Keep paired JAL candidates out of C.J range. Zcmt profiling runs + # after ordinary shortening, so near paired JALs should become C.J + # and no longer be Zcmt candidates. +.ifdef TEST_CM_JT + .space 4096 +.endif +.ifdef TEST_CM_JT_JALT + .space 4096 +.endif + + .globl foo_global + .type foo_global, %function +foo_global: + ret + + .type foo_local, %function +foo_local: + ret