diff options
author | Marc Poulhiès <poulhies@adacore.com> | 2022-06-02 09:52:21 +0200 |
---|---|---|
committer | Pierre-Marie de Rodat <derodat@adacore.com> | 2022-07-06 13:29:48 +0000 |
commit | 3202e9f88fd286a8fc4814abeaa2238d70f4d585 (patch) | |
tree | bd5a0f263e62a5019093bc0d0911062ab4b66cc5 /gcc/ada/libgnat | |
parent | b65a875a7c1a728ddb5d58fb97777394a6f773e2 (diff) | |
download | gcc-3202e9f88fd286a8fc4814abeaa2238d70f4d585.zip gcc-3202e9f88fd286a8fc4814abeaa2238d70f4d585.tar.gz gcc-3202e9f88fd286a8fc4814abeaa2238d70f4d585.tar.bz2 |
[Ada] Handle secondary stack memory allocations alignment
To accomodate cases where objects allocated on the secondary stack
needed a more constrained alignement than Standard'Maximum_Alignement,
the alignment for all allocations in the full runtime were forced on to
be aligned on Standard'Maximum_Alignement*2. This changes removes this
workaround and correctly handles the over-alignment in all runtimes.
This change modifies the SS_Allocate procedure to accept a new Alignment
parameter and to dynamically realign the pointer returned by the memory
allocation (Allocate_* functions or dedicated stack allocations for
zfp/cert).
It also simplifies the 0-sized allocations by not allocating any memory
if pointer is already correctly aligned (already the case in cert and
zfp runtimes).
gcc/ada/
* libgnat/s-secsta.ads (SS_Allocate): Add new Alignment
parameter.
(Memory_Alignment): Remove.
* libgnat/s-secsta.adb (Align_Addr): New.
(SS_Allocate): Add new Alignment parameter. Realign pointer if
needed. Don't allocate anything for 0-sized allocations.
* gcc-interface/utils2.cc (build_call_alloc_dealloc_proc): Add
allocated object's alignment as last parameter to allocation
invocation.
Diffstat (limited to 'gcc/ada/libgnat')
-rw-r--r-- | gcc/ada/libgnat/s-secsta.adb | 73 | ||||
-rw-r--r-- | gcc/ada/libgnat/s-secsta.ads | 26 |
2 files changed, 68 insertions, 31 deletions
diff --git a/gcc/ada/libgnat/s-secsta.adb b/gcc/ada/libgnat/s-secsta.adb index ac929c0..24b7601 100644 --- a/gcc/ada/libgnat/s-secsta.adb +++ b/gcc/ada/libgnat/s-secsta.adb @@ -550,22 +550,52 @@ package body System.Secondary_Stack is procedure SS_Allocate (Addr : out Address; - Storage_Size : Storage_Count) + Storage_Size : Storage_Count; + Alignment : SSE.Storage_Count := Standard'Maximum_Alignment) is + function Round_Up (Size : Storage_Count) return Memory_Size; pragma Inline (Round_Up); -- Round Size up to the nearest multiple of the maximum alignment + function Align_Addr (Addr : Address) return Address; + pragma Inline (Align_Addr); + -- Align Addr to the next multiple of Alignment + + ---------------- + -- Align_Addr -- + ---------------- + + function Align_Addr (Addr : Address) return Address is + Int_Algn : constant Integer_Address := Integer_Address (Alignment); + Int_Addr : constant Integer_Address := To_Integer (Addr); + begin + + -- L : Alignment + -- A : Standard'Maximum_Alignment + + -- Addr + -- L | L L + -- A--A--A--A--A--A--A--A--A--A--A + -- | | + -- \----/ | | + -- Addr mod L | Addr + L + -- | + -- Addr + L - (Addr mod L) + + return To_Address (Int_Addr + Int_Algn - (Int_Addr mod Int_Algn)); + end Align_Addr; + -------------- -- Round_Up -- -------------- function Round_Up (Size : Storage_Count) return Memory_Size is - Algn_MS : constant Memory_Size := Memory_Alignment; + Algn_MS : constant Memory_Size := Standard'Maximum_Alignment; Size_MS : constant Memory_Size := Memory_Size (Size); begin - -- Detect a case where the Storage_Size is very large and may yield + -- Detect a case where the Size is very large and may yield -- a rounded result which is outside the range of Chunk_Memory_Size. -- Treat this case as secondary-stack depletion. @@ -581,27 +611,46 @@ package body System.Secondary_Stack is Stack : constant SS_Stack_Ptr := Get_Sec_Stack.all; Mem_Size : Memory_Size; + Over_Aligning : constant Boolean := + Alignment > Standard'Maximum_Alignment; + + Padding : SSE.Storage_Count := 0; + -- Start of processing for SS_Allocate begin - -- Round the requested size up to the nearest multiple of the maximum - -- alignment to ensure efficient access. + -- Alignment must be a power of two and can be: - if Storage_Size = 0 then - Mem_Size := Memory_Alignment; - else - -- It should not be possible to request an allocation of negative - -- size. + -- - lower than or equal to Maximum_Alignment, in which case the result + -- will be aligned on Maximum_Alignment; + -- - higher than Maximum_Alignment, in which case the result will be + -- dynamically realigned. - pragma Assert (Storage_Size >= 0); - Mem_Size := Round_Up (Storage_Size); + if Over_Aligning then + Padding := Alignment; end if; + -- Round the requested size (plus the needed padding in case of + -- over-alignment) up to the nearest multiple of the default + -- alignment to ensure efficient access and that the next available + -- Byte is always aligned on the default alignement value. + + -- It should not be possible to request an allocation of negative + -- size. + + pragma Assert (Storage_Size >= 0); + Mem_Size := Round_Up (Storage_Size + Padding); + if Sec_Stack_Dynamic then Allocate_Dynamic (Stack, Mem_Size, Addr); else Allocate_Static (Stack, Mem_Size, Addr); end if; + + if Over_Aligning then + Addr := Align_Addr (Addr); + end if; + end SS_Allocate; ------------- diff --git a/gcc/ada/libgnat/s-secsta.ads b/gcc/ada/libgnat/s-secsta.ads index b75f1a3..9399fa3 100644 --- a/gcc/ada/libgnat/s-secsta.ads +++ b/gcc/ada/libgnat/s-secsta.ads @@ -69,11 +69,13 @@ package System.Secondary_Stack is procedure SS_Allocate (Addr : out Address; - Storage_Size : SSE.Storage_Count); + Storage_Size : SSE.Storage_Count; + Alignment : SSE.Storage_Count := Standard'Maximum_Alignment); -- Allocate enough space on the secondary stack of the invoking task to - -- accommodate an alloction of size Storage_Size. Return the address of the - -- first byte of the allocation in Addr. The routine may carry out one or - -- more of the following actions: + -- accommodate an allocation of size Storage_Size. Return the address of + -- the first byte of the allocation in Addr, which is a multiple of + -- Alignment. The routine may carry out one or more of the following + -- actions: -- -- * Reuse an existing chunk that is big enough to accommodate the -- requested Storage_Size. @@ -259,22 +261,8 @@ private subtype Memory_Index is Memory_Size; -- Index into the memory storage of a single chunk - Memory_Alignment : constant := Standard'Maximum_Alignment * 2; - -- The memory alignment we will want to honor on every allocation. - -- - -- At this stage, gigi assumes we can accommodate any alignment requirement - -- there might be on the data type for which the memory gets allocated (see - -- build_call_alloc_dealloc). - -- - -- The multiplication factor is intended to account for requirements - -- by user code compiled with specific arch/cpu options such as -mavx - -- on X86[_64] targets, which Standard'Maximum_Alignment doesn't convey - -- without such compilation options. * 4 would actually be needed to - -- support -mavx512f on X86, but this would incur more annoying memory - -- consumption overheads. - type Chunk_Memory is array (Memory_Size range <>) of SSE.Storage_Element; - for Chunk_Memory'Alignment use Memory_Alignment; + for Chunk_Memory'Alignment use Standard'Maximum_Alignment; -- The memory storage of a single chunk -------------- |