[PATCH] D71499: Add builtins for aligning and checking alignment of pointers and integers

Alexander Richardson via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Fri Dec 13 16:49:53 PST 2019


arichardson created this revision.
arichardson added reviewers: rsmith, aaron.ballman, theraven, fhahn.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

This change introduces three new builtins (which work on both pointers
and integers) that can be used instead of common bitwise arithmetic:
__builtin_align_up(x, alignment), __builtin_align_down(x, alignment) and
__builtin_is_aligned(x, alignment).

I originally added these builtins to the CHERI fork of LLVM a few years ago
to handle the slightly different C semantics that we use for CHERI [1].
Until recently these builtins (or sequences of other builtins) were
required to generate correct code. I have since made changes to the default
C semantics so that they are no longer strictly necessary (but using them
does generate slightly more efficient code). However, based on our
experience using them in various projects over the past few years, I
believe that adding these builtins to clang would be useful.

These builtins have the following benefit over bit-manipulation and casts
via uintptr_t:

- The named builtins clearly convey the semantics of the operation. While checking alignment using __builtin_is_aligned(x, 16) versus ((x & 15) == 0) is probably not a huge win in readably, I personally find __builtin_align_up(x, N) a lot easier to read than (x+(N-1))&~(N-1).
- They preserve the type of the argument (including const qualifiers). When using casts via uintptr_t, it is easy to cast to the wrong type or strip qualifiers such as const.
- If the alignment argument is a constant value, clang can check that it is a power-of-two and within the range of the type. Since the semantics of these builtins is well defined compared to arbitraty bit-manipulation, it is possible to add a UBSAN checker that the run-time value is a valid power-of-two. I intend to add this as a follow-up to this change.
- The builtins avoids int-to-pointer casts both in C and LLVM IR. In this patch I use the new llvm.ptrmask intrinsic to avoid the inttoptr+ptrtoint instructions that would normally be generated.
- They can be used to round up/down to the next aligned value for both integers and pointers without requiring two separate macros.

[1] In our CHERI compiler we have compilation mode where all pointers are
implemented as capabilities (essentially unforgeable 128-bit fat pointers).
In our original model, casts from uintptr_t (which is a 128-bit capability)
to an integer value returned the "offset" of the capability (i.e. the
difference between the virtual address and the base of the allocation).
This causes problems for cases such as checking the alignment: for example,
the expression `if ((uintptr_t)ptr & 63) == 0` is generally used to check
if the pointer is aligned to a multiple of 64 bytes. The problem offsets is
that any pointer to the beginning of an allocation will have an offset of
zero, so this check always succeeds in that case (even if the address is
not correctly aligned). The same issues also exist when aligning up or
down. Using the alignment builtins ensures that the address is used instead
of the offset. While I have since changed the default C semantics to return
the address instead of the offset when casting, this offset compilation
mode can still be used by setting with command-line flag.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D71499

Files:
  clang/include/clang/Basic/Builtins.def
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/lib/AST/ExprConstant.cpp
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/lib/CodeGen/CodeGenFunction.h
  clang/lib/Sema/SemaChecking.cpp
  clang/test/CodeGen/builtin-align-array.c
  clang/test/CodeGen/builtin-align.c
  clang/test/Sema/builtin-align.c
  clang/test/SemaCXX/builtin-align-cxx.cpp

-------------- next part --------------
A non-text attachment was scrubbed...
Name: D71499.233895.patch
Type: text/x-patch
Size: 33787 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20191214/16acee97/attachment-0001.bin>


More information about the cfe-commits mailing list