[all] Remove dependencies on non-freestanding libc
This is the first of two rather big changes to clean up includes throughout the project. In this commit, the implicit semi-dependency on libc that bonnibel adds to every module is removed. Previously, I was sloppy with includes of libc headers and include directory order. Now, the freestanding headers from libc are split out into libc_free, and an implicit real dependency is added onto this module, unless `no_libc` is set to `True`. The full libc needs to be explicitly specified as a dependency to be used. Several things needed to change in order to do this: - Many places use `memset` or `memcpy` that cannot depend on libc. The kernel has basic implementations of them itself for this reason. Now those functions are moved into the lower-level `j6/memutils.h`, and libc merely references them. Other modules are now free to reference those functions from libj6 instead. - The kernel's `assert.h` was renamed kassert.h (matching its `kassert` function) so that the new `util/assert.h` can use `__has_include` to detect it and make sure the `assert` macro is usable in libutil code. - Several implementation header files under `__libj6/` also moved under the new libc_free. - A new `include_phase` property has been added to modules for Bonnibel, which can be "normal" (default) or "late" which uses `-idirafter` instead of `-I` for includes. - Since `<utility>` and `<new>` are not freestanding, implementations of `remove_reference`, `forward`, `move`, and `swap` were added to the `util` namespace to replace those from `std`, and `util/new.h` was added to declare `operator new` and `operator delete`.
This commit is contained in:
72
src/libraries/j6/memutils.cpp
Normal file
72
src/libraries/j6/memutils.cpp
Normal file
@@ -0,0 +1,72 @@
|
||||
#include <stddef.h>
|
||||
#include <j6/memutils.h>
|
||||
#include <__j6libc/bits.h>
|
||||
#include <__j6libc/casts.h>
|
||||
#include "copy.h"
|
||||
|
||||
using namespace j6;
|
||||
using namespace __j6libc;
|
||||
|
||||
void *memcpy(void * restrict s1, const void * restrict s2, size_t n) {
|
||||
asm volatile ("rep movsb" : "+D"(s1), "+S"(s2), "+c"(n) :: "memory");
|
||||
return s1;
|
||||
}
|
||||
|
||||
static void memmove_dispatch(char *s1, const char *s2, size_t n) {
|
||||
if (s1 == s2) return;
|
||||
|
||||
if (s1 < s2 || s1 > s2 + n)
|
||||
memcpy(s1, s2, n);
|
||||
else
|
||||
do_backward_copy(s1, s2, n);
|
||||
}
|
||||
|
||||
void *memmove(void * restrict s1, const void * restrict s2, size_t n) {
|
||||
memmove_dispatch(
|
||||
reinterpret_cast<char*>(s1),
|
||||
reinterpret_cast<const char*>(s1),
|
||||
n);
|
||||
|
||||
return s1;
|
||||
}
|
||||
|
||||
#if __UINTPTR_WIDTH__ != 64 && __UINTPTR_WIDTH__ != 32
|
||||
#error "memset: uintptr_t isn't 4 or 8 bytes"
|
||||
#endif
|
||||
|
||||
static inline uintptr_t repval(uint8_t c) {
|
||||
uintptr_t r = c;
|
||||
r |= r << 8;
|
||||
r |= r << 16;
|
||||
#if __UINTPTR_WIDTH__ == 64
|
||||
r |= r << 32;
|
||||
#endif
|
||||
return r;
|
||||
}
|
||||
|
||||
void *memset(void *s, int c, size_t n) {
|
||||
if (!s) return nullptr;
|
||||
|
||||
// First, any unalined initial bytes
|
||||
uint8_t *b = cast_to<uint8_t*>(s);
|
||||
uint8_t bval = c & 0xff;
|
||||
while (n && !is_aligned<uintptr_t>(b)) {
|
||||
*b++ = bval;
|
||||
--n;
|
||||
}
|
||||
|
||||
// As many word-sized writes as possible
|
||||
size_t words = n >> word_shift;
|
||||
uintptr_t pval = repval(c);
|
||||
uintptr_t *p = cast_to<uintptr_t*>(b);
|
||||
for (size_t i = 0; i < words; ++i)
|
||||
*p++ = pval;
|
||||
|
||||
// Remaining unaligned bytes
|
||||
b = reinterpret_cast<uint8_t*>(p);
|
||||
size_t remainder = n & word_align_mask;
|
||||
for (size_t i = 0; i < remainder; ++i)
|
||||
*b++ = bval;
|
||||
|
||||
return s;
|
||||
}
|
||||
Reference in New Issue
Block a user