diff mbox

69759 - document __builtin_alloca and __builtin_alloca_with_align

Message ID 56C2951E.1040304@gmail.com
State New
Headers show

Commit Message

Martin Sebor Feb. 16, 2016, 3:18 a.m. UTC
On 02/15/2016 04:18 PM, Joseph Myers wrote:
> The description here is self-contradictory; __BIGGEST_ALIGNMENT__ bytes is
> often different from the greatest fundamental alignment (fundamental
> alignments and max_align_t only consider standard C types,
> __BIGGEST_ALIGNMENT__ can allow for e.g. vector type extensions).

Thank you for reviewing the patch.  You're right that I conflated
fundamental alignment with the strictest alignment.  I've adjusted
the description to make a distinction between __BIGGEST_ALIGNMENT__
and _Alignof(max_align_t) since they, as you point out, need not be
the same (for example on i386 Linux with GLIBC I see that the former
is 16 while the latter 8, which is correct because on GLIBC's malloc
returns 8-byte aligned pointers).  I've also fixed a few typos and
made additional adjustments to reflect the fixes in my patch for
bug 69780 that I anticipate committing later this week.

That said, I think it's worth pointing out that max_align_t has
nothing to do with standard C types.  The intent of the type is
to expose a type with the strictest alignment supported by
an implementation for an object of any type and with any storage
duration, not the alignment of the most strictly aligned basic
(or fundamental) type.

Martin

Comments

Joseph Myers Feb. 16, 2016, 1:44 p.m. UTC | #1
On Tue, 16 Feb 2016, Martin Sebor wrote:

> That said, I think it's worth pointing out that max_align_t has
> nothing to do with standard C types.  The intent of the type is
> to expose a type with the strictest alignment supported by
> an implementation for an object of any type and with any storage
> duration, not the alignment of the most strictly aligned basic
> (or fundamental) type.

The minimum alignment for max_align_t (given the proposed fix for DR#445) 
is defined in terms of standard types (where if various extensions in TRs 
and TSes are implemented, the types in those are standard types for this 
purpose).  While an implementation may choose to use a larger alignment 
than the minimum, it's inefficient to do so, considering that malloc must 
return suitably aligned memory even when the size allocated is smaller 
than the alignment (and GCC chooses to use the minimum, modulo taking the 
alignments that long long and long double have outside structures rather 
than their possibly smaller alignments inside structures).
Martin Sebor Feb. 16, 2016, 3:43 p.m. UTC | #2
On 02/16/2016 06:44 AM, Joseph Myers wrote:
> On Tue, 16 Feb 2016, Martin Sebor wrote:
>
>> That said, I think it's worth pointing out that max_align_t has
>> nothing to do with standard C types.  The intent of the type is
>> to expose a type with the strictest alignment supported by
>> an implementation for an object of any type and with any storage
>> duration, not the alignment of the most strictly aligned basic
>> (or fundamental) type.
>
> The minimum alignment for max_align_t (given the proposed fix for DR#445)
> is defined in terms of standard types (where if various extensions in TRs
> and TSes are implemented, the types in those are standard types for this
> purpose).  While an implementation may choose to use a larger alignment
> than the minimum, it's inefficient to do so, considering that malloc must
> return suitably aligned memory even when the size allocated is smaller
> than the alignment (and GCC chooses to use the minimum, modulo taking the
> alignments that long long and long double have outside structures rather
> than their possibly smaller alignments inside structures).

Max_align_t need not impact efficiency.  In C, the malloc alignment
also need not have an impact on the type since aligned_alloc returns
storage that is (or can be) more strictly aligned.

The original intent of max_align_t was to make it possible to query
the strictest alignment that an object can be defined with, regardless
of where it was defined (with what storage duration).  In C++, this
alignment is constrained by dynamic allocation because there's no way
(yet) to request overaligned heap memory (C++ doesn't specify
aligned_alloc()).  Since C does provide aligned_alloc() to allocate
overaligned memory, max_align_t is more likely to be constrained by
the other storage durations.  So for example on a C implementation
like Linux with GLIBC, while conforming, to define max_align_t to
_Alignof(long double) is redunant and less than useful.  Programs
can trivially query the alignment of basic types.  What they cannot
do (but may need to do) is query the greatest supported alignment in
all contexts/storage durations.

Martin
Joseph Myers Feb. 16, 2016, 3:54 p.m. UTC | #3
On Tue, 16 Feb 2016, Martin Sebor wrote:

> Max_align_t need not impact efficiency.  In C, the malloc alignment
> also need not have an impact on the type since aligned_alloc returns
> storage that is (or can be) more strictly aligned.

As per the DR#445 resolution, malloc must return memory "whose alignment 
is the greatest fundamental alignment".  It's obviously necessary for 
malloc to return memory sufficiently aligned for any object that can be 
declared within the standard without using over-aligned types.

As per DR#075, this applies even to malloc (1).  If max_align_t is 
64-byte-aligned, malloc (1) must return 64-byte-aligned memory.

As a practical matter of ABI compatibility, standard typedefs such as 
max_align_t should not depend on options for e.g. vector ISA extensions 
that might affect what alignments are useful (and if a change is needed, 
it should be a one-off change, only increasing the alignment and not 
depending on such ISA options).  They should also avoid depending on 
details of implementation limits (e.g. if GCC supports 2^63 byte alignment 
for ELF in future, that shouldn't need to change max_align_t).

> the other storage durations.  So for example on a C implementation
> like Linux with GLIBC, while conforming, to define max_align_t to
> _Alignof(long double) is redunant and less than useful.  Programs
> can trivially query the alignment of basic types.  What they cannot
> do (but may need to do) is query the greatest supported alignment in
> all contexts/storage durations.

If you disregard malloc, that is effectively unbounded (2^28 bytes at 
least), with current GCC on ELF targets.  This is not a useful thing to 
query, and not useful for malloc to be required to return memory aligned 
to.
diff mbox

Patch

PR c/69759 - __builtin_alloca and __builtin_alloca_with_align undocumented

gcc/ChangeLog:
2016-02-15  Martin Sebor  <msebor@redhat.com>

	PR c/69759
	* doc/extend.texi (Other Builtins): Document __builtin_alloca and
	__builtin_alloca_with_align.

Index: gcc/doc/extend.texi
===================================================================
--- gcc/doc/extend.texi	(revision 233367)
+++ gcc/doc/extend.texi	(working copy)
@@ -10144,6 +10144,8 @@  in the Cilk Plus language manual which c
 @node Other Builtins
 @section Other Built-in Functions Provided by GCC
 @cindex built-in functions
+@findex __builtin_alloca
+@findex __builtin_alloca_with_align
 @findex __builtin_call_with_static_chain
 @findex __builtin_fpclassify
 @findex __builtin_isfinite
@@ -10690,6 +10692,93 @@  In the same fashion, GCC provides @code{
 @code{__builtin_} prefixed.  The @code{isinf} and @code{isnan}
 built-in functions appear both with and without the @code{__builtin_} prefix.
 
+@deftypefn {Built-in Function} void* __builtin_alloca (size_t size)
+The @code{__builtin_alloca} function must be called at block scope.
+The function allocates an object @var{size} bytes large on the stack of
+the calling function.  The object is aligned at the greatest supported
+alignment boundary for the target.  The greatest supported alignment
+is the value of the @code{__BIGGEST_ALIGNMENT__} macro.  Portable C11
+and C++11 (or later) programs can obtain a similar value by evaluating
+the @code{_Alignof (max_align_t)} and @code{alignof (std::max_align_t)}
+expressions, respectively, which yield an alignment suitable for any
+standard type in each language.  @code{__builtin_alloca} returns a pointer
+to the first byte of the allocated object.  The lifetime of the allocated
+object ends just before the calling function returns to its caller.   This
+is so even when @code{__builtin_alloca_with_align} is called within a nested
+block.
+
+For example, the following function allocates eight objects of @code{n}
+bytes each on the stack, storing a pointer to each in consecutive elements
+of the array @code{a}.  It then passes the array to function @code{g()}
+which can safely use the storage pointed to by each of the array elements.
+
+@smallexample
+void f (unsigned n)
+@{
+  void *a [8];
+  for (int i = 0; i != 8; ++i)
+    a [i] = __builtin_alloca (n);
+
+  g (a, n);   // safe
+@}
+@end smallexample
+
+Since the @code{__builtin_alloca} function doesn't validate its arguments
+it is the responsibility of its caller to make sure the argument doesn't
+cause it doesn't exceed the stack size limit.
+The @code{__builtin_alloca} function is provided to make it possible to
+allocate arrays with a runtime bound on the stack.  Since C99 variable
+length arrays offer similar functionality under a portable, more convenient,
+and safer interface they are recommended instead, in both C99 and C++
+programs where GCC provides them as an extension.
+
+@end deftypefn
+
+@deftypefn {Built-in Function} void* __builtin_alloca_with_align (size_t size, size_t align)
+The @code{__builtin_alloca_with_align} function must be called at block
+scope.  The function allocates an object @var{size} bytes large on
+the stack of the calling function.  The allocated object is aligned on
+the boundary specified by the argument @var{align} whose unit is given
+in bits (not bytes).  @var{size} must be positive and not exceed the stack
+size limit.  @var{align} must be a constant integer expression that
+evaluates to a power of 2 greater than or equal to @code{__CHAR_BIT__}.
+Invocations with other values are rejected with an error.  The function
+returns a pointer to the first byte of the allocated object.  The lifetime
+of the allocated object ends at the end of the block in which the function
+was called.  The allocated storage is released no later than just before
+the calling function returns to its caller, but may be released as early
+as when control leaves the block in which the function was called.
+
+For example, in the following function the call to @code{g()} is unsafe
+because when @code{overalign} is non-zero, the space allocated by
+@code{__builtin_alloca_with_align} may have been released at the end
+of the @code{if} statement in which it was called.
+
+@smallexample
+void f (unsigned n, bool overalign)
+@{
+  void *p;
+  if (overalign)
+    p = __builtin_alloca_with_align (n, 64);
+  else
+    p = __builtin_alloc (n);
+
+  g (p, n);   // unsafe
+@}
+@end smallexample
+
+Since the @code{__builtin_alloca_with_align} function doesn't validate
+the @code{size} argument it is the responsibility of its caller to make
+sure the argument doesn't cause it to exceed the stack size limit.
+The @code{__builtin_alloca_with_align} function is provided to make
+it possible to allocate overaligned arrays with a runtime bound on
+the stack.  Since C99 variable length arrays offer the same functionality
+under a portable, more convenient, and safer interface they are recommended
+instead, in both C99 and C++ programs where GCC provides them as
+an extension.
+
+@end deftypefn
+
 @deftypefn {Built-in Function} int __builtin_types_compatible_p (@var{type1}, @var{type2})
 
 You can use the built-in function @code{__builtin_types_compatible_p} to