#include "wccmalloc.h"

// This must be redefined for each new benchmark

// Wasm loop bounds

__attribute__((import_module("__pragma"), import_name("loopbound"))) extern void
__pragma_loopbound(unsigned int min_bound, unsigned int max_bound);

#define HEAP_SIZE 30000

char susan_simulated_heap[HEAP_SIZE];
unsigned int susan_freeHeapPos;

__attribute__((always_inline)) static inline void *
susan_wccmalloc(unsigned int numberOfBytes) {
    // Get a 4-byte adress for alignment purposes
    unsigned int offset =
        ((unsigned long) susan_simulated_heap + susan_freeHeapPos) % 4;
    if (offset)
        susan_freeHeapPos += 4 - offset;
    void *currentPos = (void *) &susan_simulated_heap[susan_freeHeapPos];
    susan_freeHeapPos += numberOfBytes;
    return currentPos;
}
__attribute__((always_inline)) static inline void
susan_wccfreeall(void) {
    susan_freeHeapPos = 0;
}

__attribute__((always_inline)) static inline void *
susan_wccmemcpy(void *dstpp, const void *srcpp, unsigned int len) {
    unsigned long int dstp = (long int) dstpp;
    unsigned long int srcp = (long int) srcpp;

    __pragma_loopbound(76, 76);
    while (len > 0) {
        char __x = ((char *) srcp)[0];
        srcp += 1;
        len -= 1;
        ((char *) dstp)[0] = __x;
        dstp += 1;
    }

    return dstpp;
}

__attribute__((always_inline)) static inline void
susan_wccmemset(void *p, int value, unsigned int num) {
    unsigned long i;
    char *char_ptr = (char *) p;

    __pragma_loopbound(7220, 7220);
    for (i = 0; i < num; ++i)
        *char_ptr++ = (unsigned char) value;
}
