[PATCH v3 04/11] s390: Represent FP/RA saved in register in SFrame

Jens Remus jremus@linux.ibm.com
Mon Jul 7 14:36:27 GMT 2025


Hello Indu,

thank you for the review and feedback!

On 06.07.2025 01:03, Indu Bhagat via Binutils wrote:
> On 6/27/25 4:08 AM, Jens Remus wrote:
>> GCC on s390x, when in a leaf function, can be observed to save the
>> frame pointer (FP) and/or return address (RA) register in a floating-
>> point registers (FPR) instead of on the stack.  This is declared using
>> the following CFI directive:
>>
>>    .cfi_register <fp/ra-regnum>, <fpr-regnum>
>>
>> SFrame cannot represent the FP and/or RA being saved in another
>> register.  It does only track the CFA base register (SP/FP), CFA offset
>> from CFA base register, and FP and RA save area offsets from CFA.
>>
>> On s390x the FP and/or RA are only saved in another FPR when in a leaf
>> function.  That is a function that does not call any other function.
>> Therefore it can ever only be the topmost function in a call chain.
>> An unwinder by default has access to all registers of the function that
>> is the topmost on the call stack.  Therefore no further information
>> is required to restore FP/RA from the FPR.
>>
>> Represent FP/RA saved in another register on s390x, by encoding the
>> DWARF register number shifted by one to the left with the least-
>> significant bit set in the offset as follows:
>>
>>    offset = (regnum << 1) | 1
>>
>> The use of the least-significant bit of the offset as indication is
>> possible, as the stack pointer (SP), the CFA, and any register save
>> area slots are 8-byte aligned according to the s390x ELF ABI:
>> - The stack pointer (SP) "shall maintain an 8-byte alignment". [1]
>> - The CFA is defined as SP at call site +160. [2]
>> - Pointers and 8-byte integers, such as general register values, must
>>    be 8-byte aligned. [3]
>> SFrame FP and RA stack offsets must therefore always be a multiple of
>> 8 on s390x.  Note that for the same reason the DWARF data alignment
>> factor is -8 on s390x (see DWARF2_CIE_DATA_ALIGNMENT).
>>
>> Add s390x-specific SFrame (error) tests for FP/RA saved in FPRs in leaf
>> function.
>>
>> [1]: s390x ELF ABI, sections "Register Roles" and "Stack Frame
>>       Allocation", https://github.com/IBM/s390x-abi/releases
>> [2]: s390x ELF ABI, commit 4e38ad9c8a88 ("Document the CFA"),
>>       https://github.com/IBM/s390x-abi/commit/4e38ad9c8a88
>> [3]: s390x ELF ABI, section "Fundamental Types", table "Scalar types",
>>       https://github.com/IBM/s390x-abi/releases
>>
>> include/
>>     * sframe.h (SFRAME_S390X_OFFSET_IS_REGNUM): New s390x-specific
>>     macro to test whether an SFrame FP/RA offset is a DWARF register
>>     number.
>>     (SFRAME_S390X_OFFSET_ENCODE_REGNUM): New s390x-specific macro to
>>     encode a DWARF register number into an SFrame FP/RA offset.
>>     (SFRAME_S390X_OFFSET_DECODE_REGNUM): New s390x-specific macro to
>>     decode an SFrame FP/RA offset into a DWARF register number.
>>     * sframe-api.h (sframe_fre_get_fp_offset,
>>     sframe_fre_get_fp_offset): Add comment that for s390x the offset
>>     may be an encoded register number.
>>
>> gas/
>>     * gen-sframe.c (s390_sframe_xlate_do_register): New S390-
>>     specific function.  Uses SFRAME_S390X_OFFSET_ENCODE_REGNUM to
>>     represent FP/RA saved in another register on s390x.
>>     (sframe_xlate_do_register): Invoke s390_sframe_xlate_do_register
>>     on s390x.
>>
>> libsframe/
>>     * sframe.c (sframe_fre_get_fp_offset, sframe_fre_get_fp_offset):
>>     Add comment that for s390x the offset may be an encoded register
>>     number.
>>     * sframe-dump.c (is_sframe_abi_arch_s390x): New helper to test
>>     whether ABI/arch is s390x.
>>     (dump_sframe_func_with_fres): Use SFRAME_S390X_OFFSET_IS_REGNUM
>>     and SFRAME_S390X_OFFSET_DECODE_REGNUM to dump FP/RA saved in
>>     another register on s390x.
>>     * doc/sframe-spec.texi (s390x): Document s390x-specific
>>     representation of FP/RA saved in another register.
>>
>> gas/testsuite/
>>     * gas/cfi-sframe/cfi-sframe.exp: Update s390x-specific SFrame
>>     (error) tests.
>>     * gas/cfi-sframe/cfi-sframe-s390x-fpra-register-err-2.s: Rename
>>     to ...
>>     * gas/cfi-sframe/cfi-sframe-s390x-fpra-register-err-2.d:
>>     Likewise.
>>     * gas/cfi-sframe/cfi-sframe-s390x-fpra-register-1.s: This.  Test
>>     no longer triggers a warning, as SFrame can represent FP and RA
>>     saved in registers.
>>     * gas/cfi-sframe/cfi-sframe-s390x-fpra-register-1.d: Likewise.
>>     * gas/cfi-sframe/cfi-sframe-s390x-fpra-register-err-1.d: Test
>>     now triggers a different warning, as SFrame can represent FP and
>>     RA saved in registers, but not FP without RA saved in register.
>>
>> Signed-off-by: Jens Remus <jremus@linux.ibm.com>
> 
> Few nits below.
> 
> Otherwise, LGTM.
> Reviewed-by: Indu Bhagat <indu.bhagat@oracle.com>

>> diff --git a/gas/gen-sframe.c b/gas/gen-sframe.c

>> @@ -1126,6 +1126,37 @@ 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,
>> +                   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_bp_track (cur_fre,
>> +                 SFRAME_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_S390X_OFFSET_ENCODE_REGNUM (cfi_insn->u.rr.reg2));
>> +
>> +  /* Safe to skip.  */
>> +  return SFRAME_XLATE_OK;
> 
> Remove comment "Safe to skip."

Makes sense.

>> +}

>> diff --git a/include/sframe.h b/include/sframe.h

>> @@ -347,6 +347,19 @@ typedef struct sframe_frame_row_entry_addr4
>>      SP value offset from CFA is -160.  */
>>   #define SFRAME_S390X_SP_VAL_OFFSET            (-160)
>>   +/* On s390x, the FP and RA registers can be saved either on the stack or,
>> +   in case of leaf functions, in registers.  Store DWARF register numbers
>> +   encoded as offset by using the least-significant bit (LSB) as indicator:
>> +   - LSB=0: Stack offset.  The s390x ELF ABI mandates that stack register
>> +     slots must be 8-byte aligned.
>> +   - LSB=1: DWARF register number shifted to the left by one.  */
>> +#define SFRAME_S390X_OFFSET_IS_REGNUM(offset) \
>> +  ((offset) & 1)
>> +#define SFRAME_S390X_OFFSET_ENCODE_REGNUM(regnum) \
>> +  (((regnum) << 1) | 1)
>> +#define SFRAME_S390X_OFFSET_DECODE_REGNUM(offset) \
>> +  ((offset) >> 1)
>> +
> 
> Perhaps it wont hurt to also use "SFRAME_V2" as prefix in the names:
>  - SFRAME_V2_S390X_OFFSET_IS_REGNUM
>  - SFRAME_V2_S390X_OFFSET_ENCODE_REGNUM
>  - SFRAME_V2_S390X_OFFSET_ENCODE_REGNUM
> 
> This also aligns well with the choice made in the rest of the series
> (SFRAME_V2_FRE_S390X_CFA_OFFSET_ENCODE, SFRAME_V2_FRE_S390X_CFA_OFFSET_DECODE).

Ok.

Regards,
Jens
-- 
Jens Remus
Linux on Z Development (D3303)
+49-7031-16-1128 Office
jremus@de.ibm.com

IBM

IBM Deutschland Research & Development GmbH; Vorsitzender des Aufsichtsrats: Wolfgang Wendt; Geschäftsführung: David Faller; Sitz der Gesellschaft: Böblingen; Registergericht: Amtsgericht Stuttgart, HRB 243294
IBM Data Privacy Statement: https://www.ibm.com/privacy/



More information about the Binutils mailing list