std1.0.0-beta-7 SafeC docs
// SafeC Standard Library — Global Freestanding Heap
#pragma once
#include <std/stddef.h>
#include <std/heap.h>
#include <std/alloc/tlsf.h>

namespace std {

#ifdef __SAFEC_FREESTANDING__
// ── Freestanding path: static buffer + TLSF ──────────────────────────────────

extern unsigned char* memcpy(unsigned char* dst, const unsigned char* src, size_t n);

// Backing store: static array aligned to 8 bytes.
static unsigned long heap_buf_[(HEAP_SIZE + 7) / 8];  // word-aligned storage

// TLSF allocator operating over heap_buf_.
static struct TlsfAllocator heap_tlsf_;
static int heap_ready_ = 0;

// TLSF block header size (32 bytes: size + prev_phys + next_free + prev_free).
inline unsigned long heap_hdr_() {
    return (unsigned long)32;
}

inline void heap_init() {
    if (heap_ready_ != 0) { return; }
    unsafe {
        heap_tlsf_ = TlsfAllocator::over(((unsigned char*)heap_buf_)[0..(unsigned long)HEAP_SIZE]);
    }
    heap_ready_ = 1;
}

// TLSF block, 8-aligned (all TLSF guarantees); a null address when it can't.
static &heap unsigned char heap_tlsf_alloc_(unsigned long size) {
    unsigned char* p = heap_tlsf_.alloc(size, 8UL);
    unsafe { return (&heap unsigned char)p; }
}

&heap unsigned char heap_alloc(unsigned long size) {
    if (heap_ready_ == 0) { return (&heap unsigned char)0; }
    return heap_tlsf_alloc_(size);
}

inline void heap_free(&heap unsigned char ptr) {
    if (heap_ready_ == 0) { return; }
    unsafe { if ((unsigned char*)ptr == (unsigned char*)0) { return; } }
    heap_tlsf_.dealloc(ptr);
}

&heap unsigned char heap_realloc(&heap unsigned char ptr, unsigned long new_size) {
    if (heap_ready_ == 0) { return (&heap unsigned char)0; }
    unsafe { if ((unsigned char*)ptr == (unsigned char*)0) { return heap_tlsf_alloc_(new_size); } }

    &heap unsigned char new_ptr = heap_tlsf_alloc_(new_size);
    unsafe { if ((unsigned char*)new_ptr == (unsigned char*)0) { return (&heap unsigned char)0; } }

    unsafe {
        // Read old block size from the TLSF header sitting 32 bytes before data.
        struct TlsfBlock* blk = (struct TlsfBlock*)((unsigned long)ptr - heap_hdr_());
        unsigned long old_size = blk->block_size_();
        unsigned long copy_n   = old_size < new_size ? old_size : new_size;
        memcpy((unsigned char*)new_ptr, (unsigned char*)ptr, copy_n);
    }
    heap_tlsf_.dealloc(ptr);
    return new_ptr;
}

inline unsigned long heap_capacity() {
    return (unsigned long)HEAP_SIZE;
}

#else
// ── Hosted path: malloc/free/realloc wrappers ─────────────────────────────────

extern unsigned char* malloc(size_t size);
extern void  free(unsigned char* ptr);
extern unsigned char* realloc(unsigned char* ptr, size_t new_size);
extern unsigned char* memcpy(unsigned char* dst, const unsigned char* src, size_t n);

void heap_init() { }  // no-op

&heap unsigned char heap_alloc(unsigned long size) {
    unsafe { return (&heap unsigned char)malloc(size); }
}

inline void heap_free(&heap unsigned char ptr) {
    unsafe { free((unsigned char*)ptr); }
}

&heap unsigned char heap_realloc(&heap unsigned char ptr, unsigned long new_size) {
    unsafe { return (&heap unsigned char)realloc((unsigned char*)ptr, new_size); }
}

inline unsigned long heap_capacity() {
    return (unsigned long)0;  // unbounded
}

#endif

} // namespace std