Skip to content

__builtin_memcpy for large blocks - #596

Open
xavierleroy wants to merge 9 commits into
masterfrom
big-memcpy-fixes
Open

xavierleroy wants to merge 9 commits into
masterfrom
big-memcpy-fixes

Conversation

@xavierleroy

Copy link
Copy Markdown
Contributor

The expansion of __builtin_memcpy currently masks some of the high bits of the size argument off, resulting in partial copies for very large blocks (size >= 2^30, 2^34 or 2^36, depending on the target architecture).

This is very unlikely to occur in practice, but this PR fixes this problem, making sure all bits of the size argument are honored.

In passing, it also changes the expansion of __builtin_memcpy on x86-64 to take advantage of hardware optimizations on recent x86 processors, and reduces the alignment used to at most 8, which is the largest alignment supported by the CompCert back-end.

Issue (on x86-64) reported by Christos Papakonstantinou (Cantina Security).

Previously, a 32-bit move immediate was used to load `sz / 4`, resulting
in an overflow if `sz` >= 2^34.

Easy fix: use a 64-bit move immediate.  TargetPrinter will turn it into
a 32-bit move immediate when possible.
On modern x86_64 processors, it's specially optimized in hardware.

Keep the previous sequence (`rep movsl` plus corrections) for x86_32
because it's probably faster on older processors.
Use a 64-bit move immediate for `sz / 16` and do the computations in Z, not int.
Use a 64-bit move immediate and do the calculations in Z, not in int.

Note: on RV-32, `sz` is at most 2^32-1, and the 64-bit move immediate only
uses RV-32 instructions.
Do the size calculations in Z, not in int.
Do the size calculations in Z, not in int
Larger alignments are not allowed by the formal CompCert semantics.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant