[COMMITTED 34/36] [SFrame-V3] sframe: s390: gas: testsuite: enable flex FDE for s390x
Indu Bhagat
indu.bhagat@oracle.com
Fri Jan 16 06:10:34 GMT 2026
This commit amalgamates a patch set proposed by Jens Remus to enable the
SFrame Version 3 Flexible FDE Type (SFRAME_FDE_TYPE_FLEX) generation for
the s390x ABI.
Previously, s390x relied on architecture-specific encoding (shifting register
numbers into offset fields) to represent register recovery rules. This limited
the complexity of CFI that could be supported. With Flex FDE enabled:
- s390x can now represent .cfi_def_cfa using non-SP/FP registers.
- The architecture-specific function s390_sframe_xlate_do_register () in GAS
is replaced by the generic Flex FDE generation path.
- The SFrame V3 specific macros for s390x register encoding are removed
from libsframe/include, as the generic Flex FDE format handles explicit
register columns natively.
The testsuite is updated to replace negative tests (which asserted
warnings or empty SFrame generation for these patterns) with positive
tests verifying valid Flex FDE generation.
Co-authored-by: Jens Remus <jremus@linux.ibm.com>
gas/
* config/tc-s390.c (s390_support_flex_fde_p): Return true to
enable Flex FDE generation.
* gen-sframe.c (s390_sframe_xlate_do_register): Disable s390x
specific implementation.
(sframe_xlate_do_register): Invoke generic Flex FDE path now
that flex FDE generation is supported.
gas/testsuite/
* gas/cfi-sframe/cfi-sframe-s390x-err-1.d: Removed.
* gas/cfi-sframe/cfi-sframe-s390x-err-1.s: Moved to...
* gas/cfi-sframe/cfi-sframe-s390x-non-spfp-cfa-1.s: ...here.
* gas/cfi-sframe/cfi-sframe-s390x-err-2.d: Removed.
* gas/cfi-sframe/cfi-sframe-s390x-err-2.s: Moved to...
* gas/cfi-sframe/cfi-sframe-s390x-non-spfp-cfa-2.s: ...here.
* gas/cfi-sframe/cfi-sframe-s390x-fpra-register-1.d: Update to
expect Flex FDE output.
* gas/cfi-sframe/cfi-sframe-s390x-fpra-register-2.d: Likewise.
* gas/cfi-sframe/cfi-sframe.exp: Run renamed tests.
include/
* sframe.h (SFRAME_V3_S390X_OFFSET_IS_REGNUM): Remove.
(SFRAME_V3_S390X_OFFSET_ENCODE_REGNUM): Remove.
(SFRAME_V3_S390X_OFFSET_DECODE_REGNUM): Remove.
libsframe/
* sframe-dump.c (sframe_s390x_offset_regnum_p): Return false
for SFrame V3.
(sframe_s390x_offset_decode_regnum): Remove V3 support.
---
gas/config/tc-s390.c | 2 +-
gas/gen-sframe.c | 42 +------------------
.../gas/cfi-sframe/cfi-sframe-s390x-err-1.d | 15 -------
.../gas/cfi-sframe/cfi-sframe-s390x-err-2.d | 15 -------
.../cfi-sframe-s390x-fpra-register-1.d | 10 ++---
.../cfi-sframe-s390x-fpra-register-2.d | 8 ++--
.../cfi-sframe-s390x-non-spfp-cfa-1.d | 24 +++++++++++
...-1.s => cfi-sframe-s390x-non-spfp-cfa-1.s} | 0
.../cfi-sframe-s390x-non-spfp-cfa-2.d | 24 +++++++++++
...-2.s => cfi-sframe-s390x-non-spfp-cfa-2.s} | 0
gas/testsuite/gas/cfi-sframe/cfi-sframe.exp | 4 +-
include/sframe.h | 7 ++--
libsframe/sframe-dump.c | 32 ++++++++++++--
13 files changed, 93 insertions(+), 90 deletions(-)
delete mode 100644 gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-err-1.d
delete mode 100644 gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-err-2.d
create mode 100644 gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-non-spfp-cfa-1.d
rename gas/testsuite/gas/cfi-sframe/{cfi-sframe-s390x-err-1.s => cfi-sframe-s390x-non-spfp-cfa-1.s} (100%)
create mode 100644 gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-non-spfp-cfa-2.d
rename gas/testsuite/gas/cfi-sframe/{cfi-sframe-s390x-err-2.s => cfi-sframe-s390x-non-spfp-cfa-2.s} (100%)
diff --git a/gas/config/tc-s390.c b/gas/config/tc-s390.c
index 7d7c56dc8a9..535c424ca04 100644
--- a/gas/config/tc-s390.c
+++ b/gas/config/tc-s390.c
@@ -2910,7 +2910,7 @@ s390_sframe_ra_tracking_p (void)
bool
s390_support_flex_fde_p (void)
{
- return false;
+ return true;
}
/* Specify the fixed offset to recover RA from CFA.
diff --git a/gas/gen-sframe.c b/gas/gen-sframe.c
index 071d26baf31..931c14c4b02 100644
--- a/gas/gen-sframe.c
+++ b/gas/gen-sframe.c
@@ -1487,43 +1487,6 @@ sframe_xlate_do_val_offset (const struct sframe_xlate_ctx *xlate_ctx ATTRIBUTE_U
return SFRAME_XLATE_OK;
}
-/* S390-specific translate DW_CFA_register into SFrame context.
- Return SFRAME_XLATE_OK if success. */
-
-static int
-s390_sframe_xlate_do_register (struct sframe_xlate_ctx *xlate_ctx,
- const struct cfi_insn_data *cfi_insn)
-{
- /* The scratchpad FRE currently being updated with each cfi_insn
- being interpreted. This FRE eventually gets linked in into the
- list of FREs for the specific function. */
- struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre;
-
- gas_assert (cur_fre);
-
- /* Change the rule for the register indicated by the register number to
- be the specified register. Encode the register number as offset by
- shifting it to the left by one and setting the least-significant bit
- (LSB). The LSB can be used to differentiate offsets from register
- numbers, as offsets from CFA are always a multiple of -8 on s390x. */
- if (cfi_insn->u.rr.reg1 == SFRAME_CFA_FP_REG)
- sframe_fre_set_fp_track (cur_fre,
- SFRAME_V2_S390X_OFFSET_ENCODE_REGNUM (cfi_insn->u.rr.reg2));
- else if (sframe_ra_tracking_p ()
- && cfi_insn->u.rr.reg1 == SFRAME_CFA_RA_REG)
- sframe_fre_set_ra_track (cur_fre,
- SFRAME_V2_S390X_OFFSET_ENCODE_REGNUM (cfi_insn->u.rr.reg2));
- /* SFrame does not track SP explicitly. */
- else if (cfi_insn->u.rr.reg1 == SFRAME_CFA_SP_REG)
- {
- as_warn (_("no SFrame FDE emitted; %s register %u in .cfi_register"),
- sframe_register_name (cfi_insn->u.rr.reg1), cfi_insn->u.rr.reg1);
- return SFRAME_XLATE_ERR_NOTREPRESENTED; /* Not represented. */
- }
-
- return SFRAME_XLATE_OK;
-}
-
/* Translate DW_CFA_register into SFrame context.
This opcode indicates: Previous value of register1 is register2. This is
@@ -1543,10 +1506,7 @@ static int
sframe_xlate_do_register (struct sframe_xlate_ctx *xlate_ctx,
const struct cfi_insn_data *cfi_insn)
{
- /* Conditionally invoke S390-specific implementation. */
- if (sframe_get_abi_arch () == SFRAME_ABI_S390X_ENDIAN_BIG)
- return s390_sframe_xlate_do_register (xlate_ctx, cfi_insn);
- else if (sframe_support_flex_fde_p ())
+ if (sframe_support_flex_fde_p ())
{
struct sframe_row_entry *cur_fre = xlate_ctx->cur_fre;
diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-err-1.d b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-err-1.d
deleted file mode 100644
index 5cd31c7da00..00000000000
--- a/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-err-1.d
+++ /dev/null
@@ -1,15 +0,0 @@
-#name: SFrame generation on s390x - .cfi_def_cfa_register with non-SP/FP register
-#as: --gsframe
-#warning: non-SP/FP register 10 in \.cfi_def_cfa_register
-#objdump: --sframe=.sframe
-#...
-Contents of the SFrame section .sframe:
-
- Header :
-
- Version: SFRAME_VERSION_3
- Flags: SFRAME_F_FDE_FUNC_START_PCREL
- Num FDEs: 0
- Num FREs: 0
-
-#pass
diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-err-2.d b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-err-2.d
deleted file mode 100644
index 0397cd84c05..00000000000
--- a/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-err-2.d
+++ /dev/null
@@ -1,15 +0,0 @@
-#name: SFrame generation on s390x - .cfi_def_cfa with non-SP/FP register
-#as: --gsframe
-#warning: non-SP/FP register 10 in \.cfi_def_cfa
-#objdump: --sframe=.sframe
-#...
-Contents of the SFrame section .sframe:
-
- Header :
-
- Version: SFRAME_VERSION_3
- Flags: SFRAME_F_FDE_FUNC_START_PCREL
- Num FDEs: 0
- Num FREs: 0
-
-#pass
diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-fpra-register-1.d b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-fpra-register-1.d
index c53b2477cdc..63219dcae99 100644
--- a/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-fpra-register-1.d
+++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-fpra-register-1.d
@@ -1,4 +1,4 @@
-#name: SFrame generation on s390x - RA and then FP saved in registers
+#name: SFrame generation on s390x - RA and then FP saved in FPR registers
#objdump: --sframe=.sframe
#...
Contents of the SFrame section .sframe:
@@ -12,11 +12,11 @@ Contents of the SFrame section .sframe:
Function Index :
- func idx \[0\]: pc = 0x0, size = 26 bytes
+ func idx \[0\]: pc = 0x0, size = 26 bytes, attr = "F"
STARTPC +CFA +FP +RA +
0+0000 +sp\+160 +u +u +
- 0+0004 +sp\+160 +u +r16 +
- 0+0008 +sp\+160 +r17 +r16 +
- 0+0014 +sp\+160 +u +r16 +
+ 0+0004 +sp\+160 +u +r16\+0 +
+ 0+0008 +sp\+160 +r17\+0 +r16\+0 +
+ 0+0014 +sp\+160 +u +r16\+0 +
0+0018 +sp\+160 +u +u +
#pass
diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-fpra-register-2.d b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-fpra-register-2.d
index f781fb1dee9..d82b4557d94 100644
--- a/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-fpra-register-2.d
+++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-fpra-register-2.d
@@ -12,11 +12,11 @@ Contents of the SFrame section .sframe:
Function Index :
- func idx \[0\]: pc = 0x0, size = 26 bytes
+ func idx \[0\]: pc = 0x0, size = 26 bytes, attr = "F"
STARTPC +CFA +FP +RA +
0+0000 +sp\+160 +u +u +
- 0+0004 +sp\+160 +r17 +U +
- 0+0008 +sp\+160 +r17 +r16 +
- 0+0014 +sp\+160 +r17 +U +
+ 0+0004 +sp\+160 +r17\+0 +U +
+ 0+0008 +sp\+160 +r17\+0 +r16\+0 +
+ 0+0014 +sp\+160 +r17\+0 +U +
0+0018 +sp\+160 +u +u +
#pass
diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-non-spfp-cfa-1.d b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-non-spfp-cfa-1.d
new file mode 100644
index 00000000000..adf92e13232
--- /dev/null
+++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-non-spfp-cfa-1.d
@@ -0,0 +1,24 @@
+#name: SFrame generation on s390x - .cfi_def_cfa_register with non-SP/FP register
+#as: --gsframe
+#objdump: --sframe=.sframe
+#...
+Contents of the SFrame section .sframe:
+
+ Header :
+
+ Version: SFRAME_VERSION_3
+ Flags: SFRAME_F_FDE_FUNC_START_PCREL
+ Num FDEs: 1
+ Num FREs: 6
+
+ Function Index :
+
+ func idx \[0\]: pc = 0x0, size = 40 bytes, attr = "F"
+ STARTPC +CFA +FP +RA +
+ 0+0000 +sp\+160 +u +u +
+ 0+0006 +sp\+160 +c\-72 +c\-48 +
+ 0+000c +sp\+320 +c\-72 +c\-48 +
+ 0+0010 +r10\+320 +c\-72 +c\-48 +
+ 0+001c +sp\+160 +u +u +
+ 0+001e +r10\+320 +c\-72 +c\-48 +
+#pass
diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-err-1.s b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-non-spfp-cfa-1.s
similarity index 100%
rename from gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-err-1.s
rename to gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-non-spfp-cfa-1.s
diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-non-spfp-cfa-2.d b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-non-spfp-cfa-2.d
new file mode 100644
index 00000000000..5415d8431fc
--- /dev/null
+++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-non-spfp-cfa-2.d
@@ -0,0 +1,24 @@
+#name: SFrame generation on s390x - .cfi_def_cfa with non-SP/FP register
+#as: --gsframe
+#objdump: --sframe=.sframe
+#...
+Contents of the SFrame section .sframe:
+
+ Header :
+
+ Version: SFRAME_VERSION_3
+ Flags: SFRAME_F_FDE_FUNC_START_PCREL
+ Num FDEs: 1
+ Num FREs: 6
+
+ Function Index :
+
+ func idx \[0\]: pc = 0x0, size = 40 bytes, attr = "F"
+ STARTPC +CFA +FP +RA +
+ 0+0000 +sp\+160 +u +u +
+ 0+0006 +sp\+160 +c\-72 +c\-48 +
+ 0+000c +sp\+320 +c\-72 +c\-48 +
+ 0+0010 +r10\+320 +c\-72 +c\-48 +
+ 0+001c +sp\+160 +u +u +
+ 0+001e +r10\+320 +c\-72 +c\-48 +
+#pass
diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-err-2.s b/gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-non-spfp-cfa-2.s
similarity index 100%
rename from gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-err-2.s
rename to gas/testsuite/gas/cfi-sframe/cfi-sframe-s390x-non-spfp-cfa-2.s
diff --git a/gas/testsuite/gas/cfi-sframe/cfi-sframe.exp b/gas/testsuite/gas/cfi-sframe/cfi-sframe.exp
index 98af7297b2d..3f246d2da24 100644
--- a/gas/testsuite/gas/cfi-sframe/cfi-sframe.exp
+++ b/gas/testsuite/gas/cfi-sframe/cfi-sframe.exp
@@ -99,8 +99,6 @@ if { [istarget "s390x*-*-*"] && [gas_sframe_check] } then {
run_dump_test "cfi-sframe-s390x-1"
run_dump_test "cfi-sframe-s390x-2"
run_dump_test "cfi-sframe-s390x-3"
- run_dump_test "cfi-sframe-s390x-err-1"
- run_dump_test "cfi-sframe-s390x-err-2"
run_dump_test "cfi-sframe-s390x-err-3"
run_dump_test "cfi-sframe-s390x-err-4"
run_dump_test "cfi-sframe-s390x-fpra-offset-1"
@@ -109,4 +107,6 @@ if { [istarget "s390x*-*-*"] && [gas_sframe_check] } then {
run_dump_test "cfi-sframe-s390x-fpra-register-2"
run_dump_test "cfi-sframe-s390x-ra-undefined-1"
run_dump_test "cfi-sframe-s390x-pr33756"
+ run_dump_test "cfi-sframe-s390x-non-spfp-cfa-1"
+ run_dump_test "cfi-sframe-s390x-non-spfp-cfa-2"
}
diff --git a/include/sframe.h b/include/sframe.h
index 1c026d51472..2d47cc73ae8 100644
--- a/include/sframe.h
+++ b/include/sframe.h
@@ -452,9 +452,10 @@ typedef struct sframe_fre_info
offset2 (intrepreted as FP = CFA + offset2)
fi
fi
- Note that in s390x, if a FP/RA offset2/offset3 value has the least-
- significant bit set it represents a DWARF register number shifted to the
- left by 1 to restore the FP/RA value from.
+ Note that in s390x, if a FP/RA is to be restored from a register, flex FDEs
+ are used in SFrame V3. In SFrame V2, default FDEs were used: the
+ least-significant bit of the offset was set to indicate that the encoded
+ value is a DWARF register number shifted to the left by 1.
*/
/* Used when SFRAME_FRE_TYPE_ADDR1 is specified as FRE type. */
diff --git a/libsframe/sframe-dump.c b/libsframe/sframe-dump.c
index 742b60b6f4f..3d7bbafcdbc 100644
--- a/libsframe/sframe-dump.c
+++ b/libsframe/sframe-dump.c
@@ -116,6 +116,28 @@ is_sframe_abi_arch_s390x (const sframe_decoder_ctx *sfd_ctx)
return sframe_decoder_get_abi_arch (sfd_ctx) == SFRAME_ABI_S390X_ENDIAN_BIG;
}
+static bool
+sframe_s390x_offset_regnum_p (int32_t offset, uint8_t ver)
+{
+ if (ver == SFRAME_VERSION_2)
+ return SFRAME_V2_S390X_OFFSET_IS_REGNUM (offset);
+ else if (ver == SFRAME_VERSION_3)
+ return false;
+ else
+ /* No other version is supported yet. */
+ sframe_assert (false);
+}
+
+static int
+sframe_s390x_offset_decode_regnum (int32_t offset, uint8_t ver)
+{
+ if (ver == SFRAME_VERSION_2)
+ return SFRAME_V2_S390X_OFFSET_DECODE_REGNUM (offset);
+ else
+ /* No other version is supported yet. */
+ sframe_assert (false);
+}
+
static void
dump_sframe_header_flags (const sframe_decoder_ctx *sfd_ctx)
{
@@ -249,8 +271,9 @@ dump_sframe_func_fres_simple (const sframe_decoder_ctx *sfd_ctx,
if (err[1] == 0)
{
if (is_sframe_abi_arch_s390x (sfd_ctx)
- && SFRAME_V2_S390X_OFFSET_IS_REGNUM (fp_offset))
- sprintf (temp, "r%d", SFRAME_V2_S390X_OFFSET_DECODE_REGNUM (fp_offset));
+ && sframe_s390x_offset_regnum_p (fp_offset, ver))
+ sprintf (temp, "r%d",
+ sframe_s390x_offset_decode_regnum (fp_offset, ver));
else
sprintf (temp, "c%+d", fp_offset);
}
@@ -271,8 +294,9 @@ dump_sframe_func_fres_simple (const sframe_decoder_ctx *sfd_ctx,
else if (err[2] == 0)
{
if (is_sframe_abi_arch_s390x (sfd_ctx)
- && SFRAME_V2_S390X_OFFSET_IS_REGNUM (ra_offset))
- sprintf (temp, "r%d", SFRAME_V2_S390X_OFFSET_DECODE_REGNUM (ra_offset));
+ && sframe_s390x_offset_regnum_p (ra_offset, ver))
+ sprintf (temp, "r%d",
+ sframe_s390x_offset_decode_regnum (ra_offset, ver));
else
sprintf (temp, "c%+d", ra_offset);
}
--
2.43.0
More information about the Binutils
mailing list