// #include <cheriintrin.h>
// #include <stdint.h>

#include <cheriintrin.h>
#include <stdint.h>
#include <stddef.h>

#include "riscv_test.h"

void free(void * __capability ptr);
void * __capability malloc(size_t size);

void test() {

    void *__capability c1;

    // Set address
    c1 = (void *__capability)0x80001009;

    c1 = cheri_bounds_set(c1, 8);

}

// Add delta value for TLB translation
// static inline void * __capability add_delta(void * __capability cap, int offset) {
//     void * __capability result;

//     asm volatile (
//         "candperm %0, %1, %2"
//         : "=C" (result)  // Output: %0 (result)
//         : "C" (cap),     // Input:  %1 (original cap)
//           "r" (offset)   // Input:  %2 (offset register)
//         :                // No clobbered registers
//     );

//     return result;
// }

// int main(void) {
//     void *__capability csp1;

//     void *__capability base = cheri_ddc_get();

//     uintptr_t addr = 0x80001000;  // must be valid RAM in your system

//     csp1 = cheri_address_set(base, addr);
//     csp1 = cheri_bounds_set(csp1, 16);

//     csp1 = add_delta(csp1, 15);

//     *((char *__capability)csp1) = 'Z';

//     char val = *((char *__capability)csp1);
//     char val1 = *((char *__capability)csp1);

//     if (val != 'Z') {
//         while (1);
//     }

//     return 0;
// }

int main(void) {
    char * __capability a = malloc(30);
    char * __capability b = malloc(16);


    // if (!a || !b) return -1;

    a[0] = 'A';
    a[1] = 'C';
    b[0] = 'B';

    // This will fault (out-of-bounds)
    // a[20] = 'X';

    if (a[1] != 'C') {
        while (1);
    }

    if (b[0] != 'B') {
        while (1);
    }

    free(&b);
    b = NULL;

    if (b[0] == 'B') {
        while (1);
    }

    char * __capability c = malloc(16);

    // if (c[0] != 'B') {
    //     while (1);
    // }


    return 0;
}