From 3cbb7487a1a109c4fa6b5093c0f80c2731ea058e Mon Sep 17 00:00:00 2001 From: Federica Date: Mon, 17 Jul 2023 08:11:56 -0300 Subject: [PATCH 01/59] Add basic structs and runner initialization --- src/cairo_runner.c | 58 +++++++ src/cairo_runner.h | 20 +++ src/clist.c | 421 +++++++++++++++++++++++++++++++++++++++++++++ src/clist.h | 79 +++++++++ src/memory.c | 22 +++ src/memory.h | 17 ++ src/program.h | 12 ++ src/relocatable.h | 16 ++ src/run_context.h | 13 ++ src/vm.h | 12 ++ 10 files changed, 670 insertions(+) create mode 100644 src/cairo_runner.c create mode 100644 src/cairo_runner.h create mode 100644 src/clist.c create mode 100644 src/clist.h create mode 100644 src/memory.c create mode 100644 src/memory.h create mode 100644 src/program.h create mode 100644 src/relocatable.h create mode 100644 src/run_context.h create mode 100644 src/vm.h diff --git a/src/cairo_runner.c b/src/cairo_runner.c new file mode 100644 index 0000000..2b98c34 --- /dev/null +++ b/src/cairo_runner.c @@ -0,0 +1,58 @@ +#include "cairo_runner.h" +#include "relocatable.h" + +void runner_initialize_segments(cairo_runner *runner, virtual_machine *vm) +{ + // Program Segment + runner->program_base = memory_add_segment(&vm->memory); + // Execution Segment + runner->execution_base = memory_add_segment(&vm->memory); + // Initialize builtin segments +} + +void runner_initialize_state(cairo_runner *runner, virtual_machine *vm, unsigned int entrypoint) +{ + runner->initial_pc = runner->program_base; + runner->initial_pc.offset += entrypoint; + memory_load_data(&vm->memory, runner->program_base, runner->program.data); + // Mark data segment as accessed +} + +relocatable runner_initialize_function_entrypoint(cairo_runner *runner, virtual_machine *vm, unsigned int entrypoint, + CList *stack, relocatable return_fp) +{ + relocatable end = memory_add_segment(&vm->memory); + stack->add(stack, &return_fp); + stack->add(stack, &end); + runner->initial_fp.segment_index = runner->execution_base.offset; + runner->initial_fp.offset = stack->count(stack); + runner->final_pc = end; + return end; +} + +relocatable runner_initialize_main_entrypoint(cairo_runner *runner, virtual_machine *vm) +{ + CList *stack = CList_init(sizeof(union maybe_relocatable)); + // Handle builtin initial stack + // Handle proof-mode specific behaviour + relocatable return_fp = memory_add_segment(&vm->memory); + return runner_initialize_function_entrypoint(runner, vm, 0, stack, return_fp); +} + +void runner_initialize_vm(cairo_runner *runner, virtual_machine *vm) +{ + vm->run_context.ap = runner->initial_fp; + vm->run_context.fp = runner->initial_fp; + vm->run_context.pc = runner->initial_pc; + // Add validation rules + // Apply validation rules to memory +} + +relocatable runner_initialize(cairo_runner *runner, virtual_machine *vm) +{ + // runner_initialize_builtins + runner_initialize_segments(runner, vm); + relocatable end = runner_initialize_main_entrypoint(runner, vm); + runner_initialize_vm(runner, vm); + return end; +} diff --git a/src/cairo_runner.h b/src/cairo_runner.h new file mode 100644 index 0000000..1849528 --- /dev/null +++ b/src/cairo_runner.h @@ -0,0 +1,20 @@ +#ifndef RUNNER_H +#define RUNNER_H + +#include "clist.h" +#include "program.h" +#include "relocatable.h" +#include "vm.h" + +typedef struct cairo_runner +{ + struct program program; + relocatable program_base; + relocatable execution_base; + relocatable initial_pc; + relocatable initial_fp; + relocatable final_pc; + +} cairo_runner; + +#endif diff --git a/src/clist.c b/src/clist.c new file mode 100644 index 0000000..9e97ede --- /dev/null +++ b/src/clist.c @@ -0,0 +1,421 @@ +/******************************************/ +/* */ +/* Alexander Agdgomlishvili */ +/* */ +/* cdevelopment@mail.com */ +/* */ +/******************************************/ + +#include "clist.h" +#include +#include +#include +#include +#include + +typedef struct +{ + int count; /* Number of items in the list. */ + int alloc_size; /* Allocated size in quantity of items */ + int lastSearchPos; /* Position of last search - firstMatch or LastMatch */ + size_t item_size; /* Size of each item in bytes. */ + void *items; /* Pointer to the list */ +} CList_priv_; + +int CList_Realloc_(CList *l, int n) +{ + CList_priv_ *p = (CList_priv_ *)l->priv; + if (n < p->count) + { + fprintf(stderr, "CList: ERROR! Can not realloc to '%i' size - count is '%i'\n", n, p->count); + assert(n >= p->count); + return 0; + } + + if (n == 0 && p->alloc_size == 0) + n = 2; + + void *ptr = realloc(p->items, p->item_size * n); + if (ptr == NULL) + { + fprintf(stderr, "CList: ERROR! Can not reallocate memory!\n"); + return 0; + } + p->items = ptr; + p->alloc_size = n; + return 1; +} + +void *CList_Add_(CList *l, void *o) +{ + CList_priv_ *p = (CList_priv_ *)l->priv; + if (p->count == p->alloc_size && CList_Realloc_(l, p->alloc_size * 2) == 0) + return NULL; + + char *data = (char *)p->items; + data = data + p->count * p->item_size; + memcpy(data, o, p->item_size); + p->count++; + return data; +} + +void *CList_Insert_(CList *l, void *o, int n) +{ + CList_priv_ *p = (CList_priv_ *)l->priv; + if (n < 0 || n > p->count) + { + fprintf(stderr, "CList: ERROR! Insert position outside range - %d; n - %d.\n", p->count, n); + assert(n >= 0 && n <= p->count); + return NULL; + } + + if (p->count == p->alloc_size && CList_Realloc_(l, p->alloc_size * 2) == 0) + return NULL; + + size_t step = p->item_size; + char *data = (char *)p->items + n * step; + memmove(data + step, data, (p->count - n) * step); + memcpy(data, o, step); + p->count++; + return data; +} + +void *CList_Replace_(CList *l, void *o, int n) +{ + CList_priv_ *p = (CList_priv_ *)l->priv; + if (n < 0 || n >= p->count) + { + fprintf(stderr, "CList: ERROR! Replace position outside range - %d; n - %d.\n", p->count, n); + assert(n >= 0 && n < p->count); + return NULL; + } + + char *data = (char *)p->items; + data = data + n * p->item_size; + memcpy(data, o, p->item_size); + return data; +} + +void CList_Remove_(CList *l, int n) +{ + CList_priv_ *p = (CList_priv_ *)l->priv; + if (n < 0 || n >= p->count) + { + fprintf(stderr, "CList: ERROR! Remove position outside range - %d; n - %d.\n", p->count, n); + assert(n >= 0 && n < p->count); + return; + } + + size_t step = p->item_size; + char *data = (char *)p->items + n * step; + memmove(data, data + step, (p->count - n - 1) * step); + p->count--; + + if (p->alloc_size > 3 * p->count && p->alloc_size >= 4) /* Dont hold much memory */ + CList_Realloc_(l, p->alloc_size / 2); +} + +void *CList_At_(CList *l, int n) +{ + CList_priv_ *p = (CList_priv_ *)l->priv; + if (n < 0 || n >= p->count) + { + fprintf(stderr, "CList: ERROR! Get position outside range - %d; n - %d.\n", p->count, n); + assert(n >= 0 && n < p->count); + return NULL; + } + + char *data = (char *)p->items; + data = data + n * p->item_size; + return data; +} + +void *CList_firstMatch_(CList *l, const void *o, size_t shift, size_t size, int string) +{ + CList_priv_ *p = (CList_priv_ *)l->priv; + char *data = (char *)p->items; + size_t step = p->item_size; + p->lastSearchPos = -1; + + if (shift + size > p->item_size) + { + fprintf(stderr, + "CList: ERROR! Wrong ranges for firstMatch - " + "shift '%zu', size '%zu', item_size '%zu'\n", + shift, size, p->item_size); + assert(shift + size <= p->item_size); + return NULL; + } + + if (shift == 0 && size == 0) + size = p->item_size; + + size_t i = shift; + size_t end = p->count * step; + int index = 0; + + if (string) + { + for (; i < end; i += step, index++) + { + if (strncmp(data + i, o, size) == 0) + { + p->lastSearchPos = index; + return (data + i - shift); + } + } + } + else + { + for (; i < end; i += step, index++) + { + if (memcmp(data + i, o, size) == 0) + { + p->lastSearchPos = index; + return (data + i - shift); + } + } + } + + return NULL; +} + +void *CList_lastMatch_(struct CList *l, const void *o, size_t shift, size_t size, int string) +{ + CList_priv_ *p = (CList_priv_ *)l->priv; + char *data = (char *)p->items; + size_t step = p->item_size; + p->lastSearchPos = -1; + + if (shift + size > p->item_size) + { + fprintf(stderr, + "CList: ERROR! Wrong ranges for lastMatch - " + "shift '%zu', size '%zu', item_size '%zu'\n", + shift, size, p->item_size); + assert(shift + size <= p->item_size); + return NULL; + } + + if (shift == 0 && size == 0) + size = p->item_size; + + int index = p->count - 1; + long i = index * step + shift; + if (string) + { + for (; i >= 0; i -= step, index--) + { + if (strncmp(data + i, o, size) == 0) + { + p->lastSearchPos = index; + return (data + i - shift); + } + } + } + else + { + for (; i >= 0; i -= step, index--) + { + if (memcmp(data + i, o, size) == 0) + { + p->lastSearchPos = index; + return (data + i - shift); + } + } + } + + return NULL; +} + +int CList_index_(CList *l) +{ + CList_priv_ *p = (CList_priv_ *)l->priv; + return p->lastSearchPos; +} + +int CList_swap_(CList *l, int a, int b) +{ + CList_priv_ *p = (CList_priv_ *)l->priv; + + if (a < 0 || a >= p->count || b < 0 || b >= p->count) + { + fprintf(stderr, "CList: ERROR! Swap position outside range - %i, %i; count - %d.\n", a, b, p->count); + assert(a >= 0 && a < p->count && b >= 0 && b < p->count); + return 0; + } + + if (a == b) + return 1; /* ? Good ? :D */ + + char *data = (char *)p->items; + size_t step = p->item_size; + + if (p->count == p->alloc_size && CList_Realloc_(l, p->alloc_size + 1) == 0) + return 0; + + memcpy(data + p->count * step, data + a * step, step); + memcpy(data + a * step, data + b * step, step); + memcpy(data + b * step, data + p->count * step, step); + return 1; +} + +int CList_Count_(CList *l) +{ + CList_priv_ *p = (CList_priv_ *)l->priv; + return p->count; +} + +int CList_AllocSize_(CList *l) +{ + CList_priv_ *p = (CList_priv_ *)l->priv; + return p->alloc_size; +} + +size_t CList_ItemSize_(CList *l) +{ + CList_priv_ *p = (CList_priv_ *)l->priv; + return p->item_size; +} + +void CList_Clear_(CList *l) +{ + CList_priv_ *p = (CList_priv_ *)l->priv; + free(p->items); + p->items = NULL; + p->alloc_size = 0; + p->count = 0; +} + +void CList_Free_(CList *l) +{ + CList_priv_ *p = (CList_priv_ *)l->priv; + free(p->items); + free(p); + free(l); + l = NULL; +} + +void CList_print_(CList *l, size_t shift, int n, const char *type) +{ + CList_priv_ *p = (CList_priv_ *)l->priv; + + if (shift >= p->item_size) + { + fprintf(stderr, + "CList: ERROR! Wrong shift value for list print - " + "shift '%zu', item_size '%zu'\n", + shift, p->item_size); + assert(shift < p->item_size); + return; + } + + printf("\nCList: count = %i item_size = %zu alloc_size = %i type = %s\n", p->count, p->item_size, + p->alloc_size, type); + + if (n > 0) + { + int tp = -1; + if (type == NULL) + tp = 0; /* Print out pointers */ + else if (strcmp(type, "char") == 0) + tp = 1; + else if (strcmp(type, "short") == 0) + tp = 2; + else if (strcmp(type, "int") == 0) + tp = 3; + else if (strcmp(type, "long") == 0) + tp = 4; + else if (strcmp(type, "uintptr_t") == 0) + tp = 5; + else if (strcmp(type, "size_t") == 0) + tp = 6; + else if (strcmp(type, "double") == 0) + tp = 7; + else if (strcmp(type, "string") == 0) + tp = 8; + + if (tp == -1) + { + fprintf(stderr, "CList: Can not print - not supported type - %s\n\n", type); + return; + } + + n = (n > p->count) ? p->count : n; + char *data = (char *)p->items + shift; + size_t step = p->item_size; + int i = 0; + for (; i < n; i++) + { + switch (tp) + { + case 0: + printf("%p ", data); + break; + case 1: + printf("%c ", *(char *)data); + break; + case 2: + printf("%hi ", *(short *)data); + break; + case 3: + printf("%i ", *(int *)data); + break; + case 4: + printf("%li ", *(long *)data); + break; + case 5: + printf("0x%lx ", *(uintptr_t *)data); + break; + case 6: + printf("%zu ", *(size_t *)data); + break; + case 7: + printf("%f ", *(double *)data); + break; + case 8: + printf("%s\n", data); + break; + default: + return; + } + + data += step; + } + printf("\n\n"); + } +} + +CList *CList_init(size_t objSize) +{ + CList *lst = malloc(sizeof(CList)); + CList_priv_ *p = malloc(sizeof(CList_priv_)); + if (!lst || !p) + { + fprintf(stderr, "CList: ERROR! Can not allocate CList!\n"); + return NULL; + } + p->count = 0; + p->alloc_size = 0; + p->lastSearchPos = -1; + p->item_size = objSize; + p->items = NULL; + lst->add = &CList_Add_; + lst->insert = &CList_Insert_; + lst->replace = &CList_Replace_; + lst->remove = &CList_Remove_; + lst->at = &CList_At_; + lst->realloc = &CList_Realloc_; + lst->count = &CList_Count_; + lst->firstMatch = &CList_firstMatch_; + lst->lastMatch = &CList_lastMatch_; + lst->index = &CList_index_; + lst->swap = &CList_swap_; + lst->allocSize = &CList_AllocSize_; + lst->itemSize = &CList_ItemSize_; + lst->print = &CList_print_; + lst->clear = &CList_Clear_; + lst->free = &CList_Free_; + lst->priv = p; + return lst; +} diff --git a/src/clist.h b/src/clist.h new file mode 100644 index 0000000..52b5303 --- /dev/null +++ b/src/clist.h @@ -0,0 +1,79 @@ +/******************************************/ +/* */ +/* Alexander Agdgomlishvili */ +/* */ +/* cdevelopment@mail.com */ +/* */ +/******************************************/ + +#ifndef CLIST_H +#define CLIST_H + +#include +#ifdef __cplusplus +extern "C" +{ +#endif + + typedef struct CList + { + void *(*add)(struct CList *l, void *o); /* Add object to the end of a list */ + void *(*insert)(struct CList *l, void *o, int n); /* Insert object at position 'n' */ + void *(*replace)(struct CList *l, void *o, int n); /* Replace object at position 'n' */ + void (*remove)(struct CList *l, int n); /* Remove object at position 'n' */ + void *(*at)(struct CList *l, int n); /* Get object at position 'n' */ + int (*realloc)(struct CList *l, int n); /* Reallocate list to 'size' items */ + int (*count)(struct CList *l); /* Get list size in items */ + void *(*firstMatch)(struct CList *l, const void *o, size_t shift, size_t size, int string); + /* Returns object with first match of string or byte compare */ + void *(*lastMatch)(struct CList *l, const void *o, size_t shift, size_t size, int string); + /* Returns object with last match of string or byte compare */ + int (*index)(struct CList *l); /* Get index of previos search match */ + int (*swap)(struct CList *l, int a, int b); /* Swap, replace two items with index a b */ + int (*allocSize)(struct CList *l); /* Get allocated size in items */ + size_t (*itemSize)(struct CList *l); /* Get item size in bytes */ + void (*print)(struct CList *l, size_t shift, int n, const char *type); /* Print list data */ + void (*clear)(struct CList *l); /* Clear list */ + void (*free)(struct CList *l); /* Destroy struct CList and all data */ + void *priv; /* NOT FOR USE, private data */ + } CList; + + CList *CList_init(size_t objSize); /* Set list object size in bytes */ + + /* void *add(struct CList *l, void *o); + Returns pointer to added object; Returns NULL if failed. + + void *insert(struct CList *l, void *o, int n); + Returns pointer to inserted object; Returns NULL if failed. + + void *replace(struct CList *l, void *o, int n); + Returns pointer to replaced object; Returns NULL if failed. + + void *at(struct CList *l, int n); + Returns pointer to object at index n; + + int realloc(struct CList *l, int n); + Return 1 when success. Returns 0 if failed. + + void *firstMatch(struct CList *l, const void *o, size_t shift, size_t size, int string); + Returns pointer to list item when first match found. Straight scanning, from 0 to list end. + Returns NULL if search failed. + + void *lastMatch(struct CList *l, const void *o, size_t shift, size_t size, int string); + Returns pointer to list item when first match found. Reverse scanning, from list end to 0. + Returns NULL if search failed. + + int index(struct CList *l); + Returns index of last search firstMatch or lastMatch. Returns -1 if search failed. + + void print(struct CList *l, size_t shift, int n, const char *type); + Prints data of "int n" list items with offset "size_t shift" and type "const char *type". + Supported types: char, short, int, long, uintptr_t, size_t, double, string. + If type is NULL just pointers data will be printed. + */ + +#ifdef __cplusplus +} +#endif + +#endif /* CLIST_H */ diff --git a/src/memory.c b/src/memory.c new file mode 100644 index 0000000..37785a3 --- /dev/null +++ b/src/memory.c @@ -0,0 +1,22 @@ +#include "memory.h" + +relocatable memory_add_segment(memory *memory) +{ + relocatable rel = {memory->num_segments, 0}; + struct CList *segment = CList_init(sizeof(CList *)); + memory->data->add(memory->data, segment); + memory->num_segments += 1; + return rel; +} + +relocatable memory_load_data(memory *memory, relocatable ptr, CList *data) +{ + int size = data->count(data); + CList *segment = memory->data->at(memory->data, ptr.segment_index); + for (int i = 0; i < size; i++) + { + segment->insert(segment, data->at(data, i), ptr.offset + i); + } + ptr.offset += size; + return ptr; +} diff --git a/src/memory.h b/src/memory.h new file mode 100644 index 0000000..fc0258e --- /dev/null +++ b/src/memory.h @@ -0,0 +1,17 @@ +#ifndef MEMORY_H +#define MEMORY_H + +#include "clist.h" +#include "relocatable.h" +// Contains behaviour of memory + memory segment manager +typedef struct memory +{ + unsigned int num_segments; + CList *data; +} memory; + +relocatable memory_add_segment(memory *memory); + +relocatable memory_load_data(memory *memory, relocatable ptr, CList *data); + +#endif diff --git a/src/program.h b/src/program.h new file mode 100644 index 0000000..178a023 --- /dev/null +++ b/src/program.h @@ -0,0 +1,12 @@ +#ifndef PROGRAM_H +#define PROGRAM_H + +#include "clist.h" +// Incomplete struct, should be expanded +struct program +{ + unsigned int main; + CList *data; +}; + +#endif diff --git a/src/relocatable.h b/src/relocatable.h new file mode 100644 index 0000000..befdae1 --- /dev/null +++ b/src/relocatable.h @@ -0,0 +1,16 @@ +#ifndef RELOCATABLE_H +#define RELOCATABLE_H + +typedef struct relocatable +{ + unsigned int segment_index; + unsigned int offset; +} relocatable; + +typedef union maybe_relocatable +{ + struct relocatable relocatable; + unsigned int felt; // TODO use a felt type +} maybe_relocatable; + +#endif diff --git a/src/run_context.h b/src/run_context.h new file mode 100644 index 0000000..a4718aa --- /dev/null +++ b/src/run_context.h @@ -0,0 +1,13 @@ +#ifndef RUN_CONTEXT_H +#define RUN_CONTEXT_H + +#include "relocatable.h" + +typedef struct run_context +{ + relocatable pc; + relocatable ap; + relocatable fp; +} run_context; + +#endif diff --git a/src/vm.h b/src/vm.h new file mode 100644 index 0000000..955521d --- /dev/null +++ b/src/vm.h @@ -0,0 +1,12 @@ +#ifndef VM_H +#define VM_H + +#include "memory.h" +#include "run_context.h" +typedef struct virtual_machine +{ + run_context run_context; + memory memory; +} virtual_machine; + +#endif From c32247de0cfb5f4960e25ec50ff2d3cf0bd82268 Mon Sep 17 00:00:00 2001 From: Federica Date: Mon, 17 Jul 2023 09:51:44 -0300 Subject: [PATCH 02/59] Start implementing tests --- src/cairo_runner.h | 2 ++ src/memory.c | 2 ++ test/runner_tests.c | 23 +++++++++++++++++++++++ test/runner_tests.h | 9 +++++++++ test/test.c | 3 ++- 5 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 test/runner_tests.c create mode 100644 test/runner_tests.h diff --git a/src/cairo_runner.h b/src/cairo_runner.h index 1849528..62f405b 100644 --- a/src/cairo_runner.h +++ b/src/cairo_runner.h @@ -17,4 +17,6 @@ typedef struct cairo_runner } cairo_runner; +relocatable runner_initialize(cairo_runner *runner, virtual_machine *vm); + #endif diff --git a/src/memory.c b/src/memory.c index 37785a3..aae0f55 100644 --- a/src/memory.c +++ b/src/memory.c @@ -1,9 +1,11 @@ #include "memory.h" +#include relocatable memory_add_segment(memory *memory) { relocatable rel = {memory->num_segments, 0}; struct CList *segment = CList_init(sizeof(CList *)); + printf("%i, %i\n", memory->data, segment); memory->data->add(memory->data, segment); memory->num_segments += 1; return rel; diff --git a/test/runner_tests.c b/test/runner_tests.c new file mode 100644 index 0000000..ed0cf9d --- /dev/null +++ b/test/runner_tests.c @@ -0,0 +1,23 @@ +#include "runner_tests.h" +#include "program.h" +#include "vm.h" +#include "clist.h" +#include + +void initialize_runner_no_builtins_no_proof_mode_empty_program(void) { + struct CList * program_data = CList_init(sizeof(maybe_relocatable)); + struct program program = {1, program_data}; + cairo_runner runner = {program, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}}; + struct CList * mem_data = CList_init(10 * sizeof(struct CList *)); + printf("%i\n", mem_data); + virtual_machine vm = {{{0,0},{0,0},{0,0}}, {mem_data}}; + relocatable end = runner_initialize(&runner, &vm); + +} + +void runner_tests(void) { + printf("--------------------------------- \n"); + printf("Test: initialize_runner_no_builtins_no_proof_mode_empty_program \n"); + initialize_runner_no_builtins_no_proof_mode_empty_program(); +} + diff --git a/test/runner_tests.h b/test/runner_tests.h new file mode 100644 index 0000000..38ffed6 --- /dev/null +++ b/test/runner_tests.h @@ -0,0 +1,9 @@ +#ifndef RUNNER_TEST_H +#define RUNNER_TEST_H +#include +#include +#include "cairo_runner.h" + +void runner_tests(void); + +#endif diff --git a/test/test.c b/test/test.c index f6d01c5..0a3c51a 100644 --- a/test/test.c +++ b/test/test.c @@ -1,9 +1,10 @@ +#include "runner_tests.h" #include #include int main(int argc, char **argv) { - assert(1); + runner_tests(); printf("Tests passed!\n"); return 0; From 93ff6355275ea6b7aa86bff4bb729301b63c8975 Mon Sep 17 00:00:00 2001 From: Federica Date: Mon, 17 Jul 2023 11:51:01 -0300 Subject: [PATCH 03/59] Add initializers + move vm into runner + minor fixes --- src/cairo_runner.c | 48 +++++++++++++++++++++++++++------------------ src/cairo_runner.h | 5 ++++- src/clist.c | 2 +- src/memory.c | 9 +++++++-- src/memory.h | 2 ++ src/vm.c | 8 ++++++++ src/vm.h | 2 ++ test/runner_tests.c | 28 ++++++++++++-------------- test/runner_tests.h | 2 +- 9 files changed, 67 insertions(+), 39 deletions(-) create mode 100644 src/vm.c diff --git a/src/cairo_runner.c b/src/cairo_runner.c index 2b98c34..5922367 100644 --- a/src/cairo_runner.c +++ b/src/cairo_runner.c @@ -1,58 +1,68 @@ #include "cairo_runner.h" +#include "program.h" #include "relocatable.h" +#include "vm.h" -void runner_initialize_segments(cairo_runner *runner, virtual_machine *vm) +cairo_runner runner_new(struct program program) +{ + virtual_machine vm = vm_new(); + cairo_runner runner = {program, vm, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}; + return runner; +} + +void runner_initialize_segments(cairo_runner *runner) { // Program Segment - runner->program_base = memory_add_segment(&vm->memory); + runner->program_base = memory_add_segment(&runner->vm.memory); // Execution Segment - runner->execution_base = memory_add_segment(&vm->memory); + runner->execution_base = memory_add_segment(&runner->vm.memory); // Initialize builtin segments } -void runner_initialize_state(cairo_runner *runner, virtual_machine *vm, unsigned int entrypoint) +void runner_initialize_state(cairo_runner *runner, unsigned int entrypoint) { runner->initial_pc = runner->program_base; runner->initial_pc.offset += entrypoint; - memory_load_data(&vm->memory, runner->program_base, runner->program.data); + memory_load_data(&runner->vm.memory, runner->program_base, runner->program.data); // Mark data segment as accessed } -relocatable runner_initialize_function_entrypoint(cairo_runner *runner, virtual_machine *vm, unsigned int entrypoint, - CList *stack, relocatable return_fp) +relocatable runner_initialize_function_entrypoint(cairo_runner *runner, unsigned int entrypoint, CList *stack, + relocatable return_fp) { - relocatable end = memory_add_segment(&vm->memory); + relocatable end = memory_add_segment(&runner->vm.memory); stack->add(stack, &return_fp); stack->add(stack, &end); runner->initial_fp.segment_index = runner->execution_base.offset; runner->initial_fp.offset = stack->count(stack); + runner_initialize_state(runner, entrypoint); runner->final_pc = end; return end; } -relocatable runner_initialize_main_entrypoint(cairo_runner *runner, virtual_machine *vm) +relocatable runner_initialize_main_entrypoint(cairo_runner *runner) { CList *stack = CList_init(sizeof(union maybe_relocatable)); // Handle builtin initial stack // Handle proof-mode specific behaviour - relocatable return_fp = memory_add_segment(&vm->memory); - return runner_initialize_function_entrypoint(runner, vm, 0, stack, return_fp); + relocatable return_fp = memory_add_segment(&runner->vm.memory); + return runner_initialize_function_entrypoint(runner, runner->program.main, stack, return_fp); } -void runner_initialize_vm(cairo_runner *runner, virtual_machine *vm) +void runner_initialize_vm(cairo_runner *runner) { - vm->run_context.ap = runner->initial_fp; - vm->run_context.fp = runner->initial_fp; - vm->run_context.pc = runner->initial_pc; + runner->vm.run_context.ap = runner->initial_fp; + runner->vm.run_context.fp = runner->initial_fp; + runner->vm.run_context.pc = runner->initial_pc; // Add validation rules // Apply validation rules to memory } -relocatable runner_initialize(cairo_runner *runner, virtual_machine *vm) +relocatable runner_initialize(cairo_runner *runner) { // runner_initialize_builtins - runner_initialize_segments(runner, vm); - relocatable end = runner_initialize_main_entrypoint(runner, vm); - runner_initialize_vm(runner, vm); + runner_initialize_segments(runner); + relocatable end = runner_initialize_main_entrypoint(runner); + runner_initialize_vm(runner); return end; } diff --git a/src/cairo_runner.h b/src/cairo_runner.h index 62f405b..539ffdf 100644 --- a/src/cairo_runner.h +++ b/src/cairo_runner.h @@ -9,6 +9,7 @@ typedef struct cairo_runner { struct program program; + virtual_machine vm; relocatable program_base; relocatable execution_base; relocatable initial_pc; @@ -17,6 +18,8 @@ typedef struct cairo_runner } cairo_runner; -relocatable runner_initialize(cairo_runner *runner, virtual_machine *vm); +cairo_runner runner_new(struct program program); + +relocatable runner_initialize(cairo_runner *runner); #endif diff --git a/src/clist.c b/src/clist.c index 9e97ede..7822aec 100644 --- a/src/clist.c +++ b/src/clist.c @@ -350,7 +350,7 @@ void CList_print_(CList *l, size_t shift, int n, const char *type) switch (tp) { case 0: - printf("%p ", data); + printf("%s ", data); break; case 1: printf("%c ", *(char *)data); diff --git a/src/memory.c b/src/memory.c index aae0f55..eeba989 100644 --- a/src/memory.c +++ b/src/memory.c @@ -1,11 +1,16 @@ #include "memory.h" -#include + +memory memory_new(void) +{ + struct CList *mem_data = CList_init(10 * sizeof(struct CList *)); + memory mem = {0, mem_data}; + return mem; +} relocatable memory_add_segment(memory *memory) { relocatable rel = {memory->num_segments, 0}; struct CList *segment = CList_init(sizeof(CList *)); - printf("%i, %i\n", memory->data, segment); memory->data->add(memory->data, segment); memory->num_segments += 1; return rel; diff --git a/src/memory.h b/src/memory.h index fc0258e..868b7a7 100644 --- a/src/memory.h +++ b/src/memory.h @@ -10,6 +10,8 @@ typedef struct memory CList *data; } memory; +memory memory_new(void); + relocatable memory_add_segment(memory *memory); relocatable memory_load_data(memory *memory, relocatable ptr, CList *data); diff --git a/src/vm.c b/src/vm.c new file mode 100644 index 0000000..fd2c108 --- /dev/null +++ b/src/vm.c @@ -0,0 +1,8 @@ +#include "vm.h" +#include "memory.h" + +virtual_machine vm_new(void) +{ + virtual_machine vm = {{{0, 0}, {0, 0}, {0, 0}}, memory_new()}; + return vm; +} diff --git a/src/vm.h b/src/vm.h index 955521d..7eaa516 100644 --- a/src/vm.h +++ b/src/vm.h @@ -9,4 +9,6 @@ typedef struct virtual_machine memory memory; } virtual_machine; +virtual_machine vm_new(void); + #endif diff --git a/test/runner_tests.c b/test/runner_tests.c index ed0cf9d..25e6ba9 100644 --- a/test/runner_tests.c +++ b/test/runner_tests.c @@ -1,23 +1,21 @@ #include "runner_tests.h" +#include "clist.h" +#include "memory.h" #include "program.h" #include "vm.h" -#include "clist.h" #include -void initialize_runner_no_builtins_no_proof_mode_empty_program(void) { - struct CList * program_data = CList_init(sizeof(maybe_relocatable)); - struct program program = {1, program_data}; - cairo_runner runner = {program, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}}; - struct CList * mem_data = CList_init(10 * sizeof(struct CList *)); - printf("%i\n", mem_data); - virtual_machine vm = {{{0,0},{0,0},{0,0}}, {mem_data}}; - relocatable end = runner_initialize(&runner, &vm); - +void initialize_runner_no_builtins_no_proof_mode_empty_program(void) +{ + struct CList *program_data = CList_init(sizeof(maybe_relocatable)); + struct program program = {1, program_data}; + cairo_runner runner = runner_new(program); + runner_initialize(&runner); } -void runner_tests(void) { - printf("--------------------------------- \n"); - printf("Test: initialize_runner_no_builtins_no_proof_mode_empty_program \n"); - initialize_runner_no_builtins_no_proof_mode_empty_program(); +void runner_tests(void) +{ + printf("--------------------------------- \n"); + printf("Test: initialize_runner_no_builtins_no_proof_mode_empty_program \n"); + initialize_runner_no_builtins_no_proof_mode_empty_program(); } - diff --git a/test/runner_tests.h b/test/runner_tests.h index 38ffed6..948259c 100644 --- a/test/runner_tests.h +++ b/test/runner_tests.h @@ -1,8 +1,8 @@ #ifndef RUNNER_TEST_H #define RUNNER_TEST_H +#include "cairo_runner.h" #include #include -#include "cairo_runner.h" void runner_tests(void); From 871638ad0a18fca627d5fa8aedb80e84eb6d13c5 Mon Sep 17 00:00:00 2001 From: Federica Date: Mon, 17 Jul 2023 12:31:09 -0300 Subject: [PATCH 04/59] Minor fixes --- src/cairo_runner.c | 2 +- src/memory.c | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/cairo_runner.c b/src/cairo_runner.c index 5922367..211620f 100644 --- a/src/cairo_runner.c +++ b/src/cairo_runner.c @@ -33,7 +33,7 @@ relocatable runner_initialize_function_entrypoint(cairo_runner *runner, unsigned relocatable end = memory_add_segment(&runner->vm.memory); stack->add(stack, &return_fp); stack->add(stack, &end); - runner->initial_fp.segment_index = runner->execution_base.offset; + runner->initial_fp.segment_index = runner->execution_base.segment_index; runner->initial_fp.offset = stack->count(stack); runner_initialize_state(runner, entrypoint); runner->final_pc = end; diff --git a/src/memory.c b/src/memory.c index eeba989..d75812e 100644 --- a/src/memory.c +++ b/src/memory.c @@ -1,8 +1,9 @@ #include "memory.h" +#include "relocatable.h" memory memory_new(void) { - struct CList *mem_data = CList_init(10 * sizeof(struct CList *)); + struct CList *mem_data = CList_init(sizeof(struct CList *)); memory mem = {0, mem_data}; return mem; } @@ -10,7 +11,7 @@ memory memory_new(void) relocatable memory_add_segment(memory *memory) { relocatable rel = {memory->num_segments, 0}; - struct CList *segment = CList_init(sizeof(CList *)); + struct CList *segment = CList_init(sizeof(maybe_relocatable)); memory->data->add(memory->data, segment); memory->num_segments += 1; return rel; From 768049f9311e9ce0cd607d75ba94ccca6f912549 Mon Sep 17 00:00:00 2001 From: Federica Date: Mon, 17 Jul 2023 13:42:43 -0300 Subject: [PATCH 05/59] Improve runner test --- test/runner_tests.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/test/runner_tests.c b/test/runner_tests.c index 25e6ba9..f2c7a94 100644 --- a/test/runner_tests.c +++ b/test/runner_tests.c @@ -1,16 +1,37 @@ #include "runner_tests.h" #include "clist.h" #include "memory.h" +#include "run_context.h" #include "program.h" #include "vm.h" +#include #include void initialize_runner_no_builtins_no_proof_mode_empty_program(void) { struct CList *program_data = CList_init(sizeof(maybe_relocatable)); - struct program program = {1, program_data}; + struct program program = {0, program_data}; cairo_runner runner = runner_new(program); runner_initialize(&runner); + // Check runner data + assert(runner.program_base.segment_index == 0 && runner.program_base.offset == 0); + assert(runner.execution_base.segment_index == 1 && runner.execution_base.offset == 0); + assert(runner.initial_pc.segment_index == 0 && runner.initial_pc.offset == 0); + assert(runner.initial_fp.segment_index == 1 && runner.initial_fp.offset == 2); + assert(runner.final_pc.segment_index == 3 && runner.final_pc.offset == 0); + // Check vm data + run_context run_context = runner.vm.run_context; + assert(run_context.pc.segment_index == 0 && run_context.pc.offset == 0); + assert(run_context.ap.segment_index == 1 && run_context.ap.offset == 2); + assert(run_context.fp.segment_index == 1 && run_context.fp.offset == 2); + // Check memory + memory memory = runner.vm.memory; + assert(memory.num_segments == 4); + assert(memory.data->count(memory.data) == 4); + // check individual segments + struct CList * segment_0 = memory.data->at(memory.data, 0); + assert(segment_0->count(segment_0) == 0); + } void runner_tests(void) From 683eca86b6923c1f2991b643bfd87c66ed396813 Mon Sep 17 00:00:00 2001 From: Federica Date: Tue, 18 Jul 2023 08:33:30 -0300 Subject: [PATCH 06/59] Fix memory new size --- src/memory.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/memory.c b/src/memory.c index d75812e..c2c1ee7 100644 --- a/src/memory.c +++ b/src/memory.c @@ -3,7 +3,7 @@ memory memory_new(void) { - struct CList *mem_data = CList_init(sizeof(struct CList *)); + struct CList *mem_data = CList_init(sizeof(struct CList)); memory mem = {0, mem_data}; return mem; } From 6982d8b7ffc10a82705b9471840fd89bb22f6506 Mon Sep 17 00:00:00 2001 From: Federica Date: Tue, 18 Jul 2023 09:49:51 -0300 Subject: [PATCH 07/59] Add memory tests --- test/memory_tests.c | 41 +++++++++++++++++++++++++++++++++++++++++ test/memory_tests.h | 9 +++++++++ test/test.c | 5 ++++- 3 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 test/memory_tests.c create mode 100644 test/memory_tests.h diff --git a/test/memory_tests.c b/test/memory_tests.c new file mode 100644 index 0000000..5f6cc52 --- /dev/null +++ b/test/memory_tests.c @@ -0,0 +1,41 @@ +#include "memory_tests.h" +#include + +void load_data_one_element(void) { + // Initialize memory + memory mem = memory_new(); + memory_add_segment(&mem); + //Initialize data to load + struct CList *data = CList_init(sizeof(maybe_relocatable)); + union maybe_relocatable elem = {.felt = 1}; + data->add(data, &elem); + relocatable ptr = {0,0}; + // Load data + memory_load_data(&mem, ptr, data); + // Check memory + assert(mem.data->count(mem.data) == 1); + maybe_relocatable * first_elem = mem.data->at(mem.data, 0); + assert( first_elem->felt == 1); +} + +void load_data_empty(void) { + // Initialize memory + memory mem = memory_new(); + memory_add_segment(&mem); + //Initialize data to load + struct CList *data = CList_init(sizeof(maybe_relocatable)); + relocatable ptr = {0,0}; + // Load data + memory_load_data(&mem, ptr, data); + // Check memory + assert(mem.data->count(mem.data) == 1); + maybe_relocatable * first_elem = mem.data->at(mem.data, 0); + assert( first_elem->felt == 1); +} + +void memory_tests(void) +{ + printf("--------------------------------- \n"); + printf("Test: load_data_one_element \n"); + load_data_one_element(); +} diff --git a/test/memory_tests.h b/test/memory_tests.h new file mode 100644 index 0000000..3765641 --- /dev/null +++ b/test/memory_tests.h @@ -0,0 +1,9 @@ +#ifndef MEMORY_TEST_H +#define MEMORY_TEST_H +#include "memory.h" +#include +#include + +void memory_tests(void); + +#endif diff --git a/test/test.c b/test/test.c index 0a3c51a..ea0c756 100644 --- a/test/test.c +++ b/test/test.c @@ -1,10 +1,13 @@ +#include "memory_tests.h" #include "runner_tests.h" +#include "memory.h" #include #include int main(int argc, char **argv) { - runner_tests(); + //runner_tests(); + memory_tests(); printf("Tests passed!\n"); return 0; From 74d742c18edb8cce78924f291f858dbcd7ab566e Mon Sep 17 00:00:00 2001 From: Federica Date: Tue, 18 Jul 2023 12:09:35 -0300 Subject: [PATCH 08/59] Implement memory_get + run new formatter --- src/cairo_runner.c | 21 +++---- src/cairo_runner.h | 3 +- src/clist.c | 137 +++++++++++++++----------------------------- src/clist.h | 94 +++++++++++++++--------------- src/memory.c | 28 ++++++--- src/memory.h | 24 +++++++- src/program.h | 3 +- src/relocatable.h | 6 +- src/run_context.h | 3 +- src/vm.c | 3 +- src/vm.h | 3 +- test/memory_tests.c | 55 +++++++++--------- test/runner_tests.c | 45 +++++++-------- test/test.c | 4 +- 14 files changed, 196 insertions(+), 233 deletions(-) diff --git a/src/cairo_runner.c b/src/cairo_runner.c index 211620f..197f380 100644 --- a/src/cairo_runner.c +++ b/src/cairo_runner.c @@ -3,15 +3,13 @@ #include "relocatable.h" #include "vm.h" -cairo_runner runner_new(struct program program) -{ +cairo_runner runner_new(struct program program) { virtual_machine vm = vm_new(); cairo_runner runner = {program, vm, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}; return runner; } -void runner_initialize_segments(cairo_runner *runner) -{ +void runner_initialize_segments(cairo_runner *runner) { // Program Segment runner->program_base = memory_add_segment(&runner->vm.memory); // Execution Segment @@ -19,8 +17,7 @@ void runner_initialize_segments(cairo_runner *runner) // Initialize builtin segments } -void runner_initialize_state(cairo_runner *runner, unsigned int entrypoint) -{ +void runner_initialize_state(cairo_runner *runner, unsigned int entrypoint) { runner->initial_pc = runner->program_base; runner->initial_pc.offset += entrypoint; memory_load_data(&runner->vm.memory, runner->program_base, runner->program.data); @@ -28,8 +25,7 @@ void runner_initialize_state(cairo_runner *runner, unsigned int entrypoint) } relocatable runner_initialize_function_entrypoint(cairo_runner *runner, unsigned int entrypoint, CList *stack, - relocatable return_fp) -{ + relocatable return_fp) { relocatable end = memory_add_segment(&runner->vm.memory); stack->add(stack, &return_fp); stack->add(stack, &end); @@ -40,8 +36,7 @@ relocatable runner_initialize_function_entrypoint(cairo_runner *runner, unsigned return end; } -relocatable runner_initialize_main_entrypoint(cairo_runner *runner) -{ +relocatable runner_initialize_main_entrypoint(cairo_runner *runner) { CList *stack = CList_init(sizeof(union maybe_relocatable)); // Handle builtin initial stack // Handle proof-mode specific behaviour @@ -49,8 +44,7 @@ relocatable runner_initialize_main_entrypoint(cairo_runner *runner) return runner_initialize_function_entrypoint(runner, runner->program.main, stack, return_fp); } -void runner_initialize_vm(cairo_runner *runner) -{ +void runner_initialize_vm(cairo_runner *runner) { runner->vm.run_context.ap = runner->initial_fp; runner->vm.run_context.fp = runner->initial_fp; runner->vm.run_context.pc = runner->initial_pc; @@ -58,8 +52,7 @@ void runner_initialize_vm(cairo_runner *runner) // Apply validation rules to memory } -relocatable runner_initialize(cairo_runner *runner) -{ +relocatable runner_initialize(cairo_runner *runner) { // runner_initialize_builtins runner_initialize_segments(runner); relocatable end = runner_initialize_main_entrypoint(runner); diff --git a/src/cairo_runner.h b/src/cairo_runner.h index 539ffdf..3daf93b 100644 --- a/src/cairo_runner.h +++ b/src/cairo_runner.h @@ -6,8 +6,7 @@ #include "relocatable.h" #include "vm.h" -typedef struct cairo_runner -{ +typedef struct cairo_runner { struct program program; virtual_machine vm; relocatable program_base; diff --git a/src/clist.c b/src/clist.c index 7822aec..6e5b0b2 100644 --- a/src/clist.c +++ b/src/clist.c @@ -13,8 +13,7 @@ #include #include -typedef struct -{ +typedef struct { int count; /* Number of items in the list. */ int alloc_size; /* Allocated size in quantity of items */ int lastSearchPos; /* Position of last search - firstMatch or LastMatch */ @@ -22,11 +21,9 @@ typedef struct void *items; /* Pointer to the list */ } CList_priv_; -int CList_Realloc_(CList *l, int n) -{ +int CList_Realloc_(CList *l, int n) { CList_priv_ *p = (CList_priv_ *)l->priv; - if (n < p->count) - { + if (n < p->count) { fprintf(stderr, "CList: ERROR! Can not realloc to '%i' size - count is '%i'\n", n, p->count); assert(n >= p->count); return 0; @@ -36,8 +33,7 @@ int CList_Realloc_(CList *l, int n) n = 2; void *ptr = realloc(p->items, p->item_size * n); - if (ptr == NULL) - { + if (ptr == NULL) { fprintf(stderr, "CList: ERROR! Can not reallocate memory!\n"); return 0; } @@ -46,8 +42,7 @@ int CList_Realloc_(CList *l, int n) return 1; } -void *CList_Add_(CList *l, void *o) -{ +void *CList_Add_(CList *l, void *o) { CList_priv_ *p = (CList_priv_ *)l->priv; if (p->count == p->alloc_size && CList_Realloc_(l, p->alloc_size * 2) == 0) return NULL; @@ -59,11 +54,9 @@ void *CList_Add_(CList *l, void *o) return data; } -void *CList_Insert_(CList *l, void *o, int n) -{ +void *CList_Insert_(CList *l, void *o, int n) { CList_priv_ *p = (CList_priv_ *)l->priv; - if (n < 0 || n > p->count) - { + if (n < 0 || n > p->count) { fprintf(stderr, "CList: ERROR! Insert position outside range - %d; n - %d.\n", p->count, n); assert(n >= 0 && n <= p->count); return NULL; @@ -80,11 +73,9 @@ void *CList_Insert_(CList *l, void *o, int n) return data; } -void *CList_Replace_(CList *l, void *o, int n) -{ +void *CList_Replace_(CList *l, void *o, int n) { CList_priv_ *p = (CList_priv_ *)l->priv; - if (n < 0 || n >= p->count) - { + if (n < 0 || n >= p->count) { fprintf(stderr, "CList: ERROR! Replace position outside range - %d; n - %d.\n", p->count, n); assert(n >= 0 && n < p->count); return NULL; @@ -96,11 +87,9 @@ void *CList_Replace_(CList *l, void *o, int n) return data; } -void CList_Remove_(CList *l, int n) -{ +void CList_Remove_(CList *l, int n) { CList_priv_ *p = (CList_priv_ *)l->priv; - if (n < 0 || n >= p->count) - { + if (n < 0 || n >= p->count) { fprintf(stderr, "CList: ERROR! Remove position outside range - %d; n - %d.\n", p->count, n); assert(n >= 0 && n < p->count); return; @@ -115,11 +104,9 @@ void CList_Remove_(CList *l, int n) CList_Realloc_(l, p->alloc_size / 2); } -void *CList_At_(CList *l, int n) -{ +void *CList_At_(CList *l, int n) { CList_priv_ *p = (CList_priv_ *)l->priv; - if (n < 0 || n >= p->count) - { + if (n < 0 || n >= p->count) { fprintf(stderr, "CList: ERROR! Get position outside range - %d; n - %d.\n", p->count, n); assert(n >= 0 && n < p->count); return NULL; @@ -130,15 +117,13 @@ void *CList_At_(CList *l, int n) return data; } -void *CList_firstMatch_(CList *l, const void *o, size_t shift, size_t size, int string) -{ +void *CList_firstMatch_(CList *l, const void *o, size_t shift, size_t size, int string) { CList_priv_ *p = (CList_priv_ *)l->priv; char *data = (char *)p->items; size_t step = p->item_size; p->lastSearchPos = -1; - if (shift + size > p->item_size) - { + if (shift + size > p->item_size) { fprintf(stderr, "CList: ERROR! Wrong ranges for firstMatch - " "shift '%zu', size '%zu', item_size '%zu'\n", @@ -154,23 +139,16 @@ void *CList_firstMatch_(CList *l, const void *o, size_t shift, size_t size, int size_t end = p->count * step; int index = 0; - if (string) - { - for (; i < end; i += step, index++) - { - if (strncmp(data + i, o, size) == 0) - { + if (string) { + for (; i < end; i += step, index++) { + if (strncmp(data + i, o, size) == 0) { p->lastSearchPos = index; return (data + i - shift); } } - } - else - { - for (; i < end; i += step, index++) - { - if (memcmp(data + i, o, size) == 0) - { + } else { + for (; i < end; i += step, index++) { + if (memcmp(data + i, o, size) == 0) { p->lastSearchPos = index; return (data + i - shift); } @@ -180,15 +158,13 @@ void *CList_firstMatch_(CList *l, const void *o, size_t shift, size_t size, int return NULL; } -void *CList_lastMatch_(struct CList *l, const void *o, size_t shift, size_t size, int string) -{ +void *CList_lastMatch_(struct CList *l, const void *o, size_t shift, size_t size, int string) { CList_priv_ *p = (CList_priv_ *)l->priv; char *data = (char *)p->items; size_t step = p->item_size; p->lastSearchPos = -1; - if (shift + size > p->item_size) - { + if (shift + size > p->item_size) { fprintf(stderr, "CList: ERROR! Wrong ranges for lastMatch - " "shift '%zu', size '%zu', item_size '%zu'\n", @@ -202,23 +178,16 @@ void *CList_lastMatch_(struct CList *l, const void *o, size_t shift, size_t size int index = p->count - 1; long i = index * step + shift; - if (string) - { - for (; i >= 0; i -= step, index--) - { - if (strncmp(data + i, o, size) == 0) - { + if (string) { + for (; i >= 0; i -= step, index--) { + if (strncmp(data + i, o, size) == 0) { p->lastSearchPos = index; return (data + i - shift); } } - } - else - { - for (; i >= 0; i -= step, index--) - { - if (memcmp(data + i, o, size) == 0) - { + } else { + for (; i >= 0; i -= step, index--) { + if (memcmp(data + i, o, size) == 0) { p->lastSearchPos = index; return (data + i - shift); } @@ -228,18 +197,15 @@ void *CList_lastMatch_(struct CList *l, const void *o, size_t shift, size_t size return NULL; } -int CList_index_(CList *l) -{ +int CList_index_(CList *l) { CList_priv_ *p = (CList_priv_ *)l->priv; return p->lastSearchPos; } -int CList_swap_(CList *l, int a, int b) -{ +int CList_swap_(CList *l, int a, int b) { CList_priv_ *p = (CList_priv_ *)l->priv; - if (a < 0 || a >= p->count || b < 0 || b >= p->count) - { + if (a < 0 || a >= p->count || b < 0 || b >= p->count) { fprintf(stderr, "CList: ERROR! Swap position outside range - %i, %i; count - %d.\n", a, b, p->count); assert(a >= 0 && a < p->count && b >= 0 && b < p->count); return 0; @@ -260,26 +226,22 @@ int CList_swap_(CList *l, int a, int b) return 1; } -int CList_Count_(CList *l) -{ +int CList_Count_(CList *l) { CList_priv_ *p = (CList_priv_ *)l->priv; return p->count; } -int CList_AllocSize_(CList *l) -{ +int CList_AllocSize_(CList *l) { CList_priv_ *p = (CList_priv_ *)l->priv; return p->alloc_size; } -size_t CList_ItemSize_(CList *l) -{ +size_t CList_ItemSize_(CList *l) { CList_priv_ *p = (CList_priv_ *)l->priv; return p->item_size; } -void CList_Clear_(CList *l) -{ +void CList_Clear_(CList *l) { CList_priv_ *p = (CList_priv_ *)l->priv; free(p->items); p->items = NULL; @@ -287,8 +249,7 @@ void CList_Clear_(CList *l) p->count = 0; } -void CList_Free_(CList *l) -{ +void CList_Free_(CList *l) { CList_priv_ *p = (CList_priv_ *)l->priv; free(p->items); free(p); @@ -296,12 +257,10 @@ void CList_Free_(CList *l) l = NULL; } -void CList_print_(CList *l, size_t shift, int n, const char *type) -{ +void CList_print_(CList *l, size_t shift, int n, const char *type) { CList_priv_ *p = (CList_priv_ *)l->priv; - if (shift >= p->item_size) - { + if (shift >= p->item_size) { fprintf(stderr, "CList: ERROR! Wrong shift value for list print - " "shift '%zu', item_size '%zu'\n", @@ -313,8 +272,7 @@ void CList_print_(CList *l, size_t shift, int n, const char *type) printf("\nCList: count = %i item_size = %zu alloc_size = %i type = %s\n", p->count, p->item_size, p->alloc_size, type); - if (n > 0) - { + if (n > 0) { int tp = -1; if (type == NULL) tp = 0; /* Print out pointers */ @@ -335,8 +293,7 @@ void CList_print_(CList *l, size_t shift, int n, const char *type) else if (strcmp(type, "string") == 0) tp = 8; - if (tp == -1) - { + if (tp == -1) { fprintf(stderr, "CList: Can not print - not supported type - %s\n\n", type); return; } @@ -345,10 +302,8 @@ void CList_print_(CList *l, size_t shift, int n, const char *type) char *data = (char *)p->items + shift; size_t step = p->item_size; int i = 0; - for (; i < n; i++) - { - switch (tp) - { + for (; i < n; i++) { + switch (tp) { case 0: printf("%s ", data); break; @@ -386,12 +341,10 @@ void CList_print_(CList *l, size_t shift, int n, const char *type) } } -CList *CList_init(size_t objSize) -{ +CList *CList_init(size_t objSize) { CList *lst = malloc(sizeof(CList)); CList_priv_ *p = malloc(sizeof(CList_priv_)); - if (!lst || !p) - { + if (!lst || !p) { fprintf(stderr, "CList: ERROR! Can not allocate CList!\n"); return NULL; } diff --git a/src/clist.h b/src/clist.h index 52b5303..9dd17a7 100644 --- a/src/clist.h +++ b/src/clist.h @@ -11,66 +11,64 @@ #include #ifdef __cplusplus -extern "C" -{ +extern "C" { #endif - typedef struct CList - { - void *(*add)(struct CList *l, void *o); /* Add object to the end of a list */ - void *(*insert)(struct CList *l, void *o, int n); /* Insert object at position 'n' */ - void *(*replace)(struct CList *l, void *o, int n); /* Replace object at position 'n' */ - void (*remove)(struct CList *l, int n); /* Remove object at position 'n' */ - void *(*at)(struct CList *l, int n); /* Get object at position 'n' */ - int (*realloc)(struct CList *l, int n); /* Reallocate list to 'size' items */ - int (*count)(struct CList *l); /* Get list size in items */ - void *(*firstMatch)(struct CList *l, const void *o, size_t shift, size_t size, int string); - /* Returns object with first match of string or byte compare */ - void *(*lastMatch)(struct CList *l, const void *o, size_t shift, size_t size, int string); - /* Returns object with last match of string or byte compare */ - int (*index)(struct CList *l); /* Get index of previos search match */ - int (*swap)(struct CList *l, int a, int b); /* Swap, replace two items with index a b */ - int (*allocSize)(struct CList *l); /* Get allocated size in items */ - size_t (*itemSize)(struct CList *l); /* Get item size in bytes */ - void (*print)(struct CList *l, size_t shift, int n, const char *type); /* Print list data */ - void (*clear)(struct CList *l); /* Clear list */ - void (*free)(struct CList *l); /* Destroy struct CList and all data */ - void *priv; /* NOT FOR USE, private data */ - } CList; +typedef struct CList { + void *(*add)(struct CList *l, void *o); /* Add object to the end of a list */ + void *(*insert)(struct CList *l, void *o, int n); /* Insert object at position 'n' */ + void *(*replace)(struct CList *l, void *o, int n); /* Replace object at position 'n' */ + void (*remove)(struct CList *l, int n); /* Remove object at position 'n' */ + void *(*at)(struct CList *l, int n); /* Get object at position 'n' */ + int (*realloc)(struct CList *l, int n); /* Reallocate list to 'size' items */ + int (*count)(struct CList *l); /* Get list size in items */ + void *(*firstMatch)(struct CList *l, const void *o, size_t shift, size_t size, int string); + /* Returns object with first match of string or byte compare */ + void *(*lastMatch)(struct CList *l, const void *o, size_t shift, size_t size, int string); + /* Returns object with last match of string or byte compare */ + int (*index)(struct CList *l); /* Get index of previos search match */ + int (*swap)(struct CList *l, int a, int b); /* Swap, replace two items with index a b */ + int (*allocSize)(struct CList *l); /* Get allocated size in items */ + size_t (*itemSize)(struct CList *l); /* Get item size in bytes */ + void (*print)(struct CList *l, size_t shift, int n, const char *type); /* Print list data */ + void (*clear)(struct CList *l); /* Clear list */ + void (*free)(struct CList *l); /* Destroy struct CList and all data */ + void *priv; /* NOT FOR USE, private data */ +} CList; - CList *CList_init(size_t objSize); /* Set list object size in bytes */ +CList *CList_init(size_t objSize); /* Set list object size in bytes */ - /* void *add(struct CList *l, void *o); - Returns pointer to added object; Returns NULL if failed. +/* void *add(struct CList *l, void *o); + Returns pointer to added object; Returns NULL if failed. - void *insert(struct CList *l, void *o, int n); - Returns pointer to inserted object; Returns NULL if failed. + void *insert(struct CList *l, void *o, int n); + Returns pointer to inserted object; Returns NULL if failed. - void *replace(struct CList *l, void *o, int n); - Returns pointer to replaced object; Returns NULL if failed. + void *replace(struct CList *l, void *o, int n); + Returns pointer to replaced object; Returns NULL if failed. - void *at(struct CList *l, int n); - Returns pointer to object at index n; + void *at(struct CList *l, int n); + Returns pointer to object at index n; - int realloc(struct CList *l, int n); - Return 1 when success. Returns 0 if failed. + int realloc(struct CList *l, int n); + Return 1 when success. Returns 0 if failed. - void *firstMatch(struct CList *l, const void *o, size_t shift, size_t size, int string); - Returns pointer to list item when first match found. Straight scanning, from 0 to list end. - Returns NULL if search failed. + void *firstMatch(struct CList *l, const void *o, size_t shift, size_t size, int string); + Returns pointer to list item when first match found. Straight scanning, from 0 to list end. + Returns NULL if search failed. - void *lastMatch(struct CList *l, const void *o, size_t shift, size_t size, int string); - Returns pointer to list item when first match found. Reverse scanning, from list end to 0. - Returns NULL if search failed. + void *lastMatch(struct CList *l, const void *o, size_t shift, size_t size, int string); + Returns pointer to list item when first match found. Reverse scanning, from list end to 0. + Returns NULL if search failed. - int index(struct CList *l); - Returns index of last search firstMatch or lastMatch. Returns -1 if search failed. + int index(struct CList *l); + Returns index of last search firstMatch or lastMatch. Returns -1 if search failed. - void print(struct CList *l, size_t shift, int n, const char *type); - Prints data of "int n" list items with offset "size_t shift" and type "const char *type". - Supported types: char, short, int, long, uintptr_t, size_t, double, string. - If type is NULL just pointers data will be printed. - */ + void print(struct CList *l, size_t shift, int n, const char *type); + Prints data of "int n" list items with offset "size_t shift" and type "const char *type". + Supported types: char, short, int, long, uintptr_t, size_t, double, string. + If type is NULL just pointers data will be printed. +*/ #ifdef __cplusplus } diff --git a/src/memory.c b/src/memory.c index d910293..c2b8161 100644 --- a/src/memory.c +++ b/src/memory.c @@ -1,17 +1,29 @@ #include "memory.h" +#include "clist.h" #include "relocatable.h" -memory memory_new(void) -{ +memory memory_new(void) { struct CList *mem_data = CList_init(sizeof(struct CList)); memory mem = {0, mem_data}; return mem; } -maybe_relocatable memory_get() +ResultMemory memory_get(memory *mem, relocatable ptr) { + if (ptr.segment_index > mem->data->count(mem->data)) { + ResultMemory error = {.is_error = true, .value = {.error = Get}}; + return error; + } + CList *segment = mem->data->at(mem->data, ptr.segment_index); + if (ptr.offset > segment->count(segment)) { + ResultMemory error = {.is_error = true, .value = {.error = Get}}; + return error; + } + maybe_relocatable *value = segment->at(segment, ptr.offset); + ResultMemory ok = {.is_error = false, .value = {.memory_value = *value}}; + return ok; +} -relocatable memory_add_segment(memory *memory) -{ +relocatable memory_add_segment(memory *memory) { relocatable rel = {memory->num_segments, 0}; struct CList *segment = CList_init(sizeof(maybe_relocatable)); memory->data->add(memory->data, segment); @@ -19,12 +31,10 @@ relocatable memory_add_segment(memory *memory) return rel; } -relocatable memory_load_data(memory *memory, relocatable ptr, CList *data) -{ +relocatable memory_load_data(memory *memory, relocatable ptr, CList *data) { int size = data->count(data); CList *segment = memory->data->at(memory->data, ptr.segment_index); - for (int i = 0; i < size; i++) - { + for (int i = 0; i < size; i++) { segment->insert(segment, data->at(data, i), ptr.offset + i); } ptr.offset += size; diff --git a/src/memory.h b/src/memory.h index 868b7a7..1f7eaec 100644 --- a/src/memory.h +++ b/src/memory.h @@ -3,9 +3,9 @@ #include "clist.h" #include "relocatable.h" +#include // Contains behaviour of memory + memory segment manager -typedef struct memory -{ +typedef struct memory { unsigned int num_segments; CList *data; } memory; @@ -16,4 +16,24 @@ relocatable memory_add_segment(memory *memory); relocatable memory_load_data(memory *memory, relocatable ptr, CList *data); +// Error handling + +enum MemoryError { + Get, + Insert, + LoadData, +}; + +union ResultMemoryValue { + enum MemoryError error; + maybe_relocatable memory_value; + relocatable ptr; + int none; +}; + +typedef struct ResultMemory { + bool is_error; + union ResultMemoryValue value; +} ResultMemory; + #endif diff --git a/src/program.h b/src/program.h index 178a023..e2b9b92 100644 --- a/src/program.h +++ b/src/program.h @@ -3,8 +3,7 @@ #include "clist.h" // Incomplete struct, should be expanded -struct program -{ +struct program { unsigned int main; CList *data; }; diff --git a/src/relocatable.h b/src/relocatable.h index befdae1..b1324e2 100644 --- a/src/relocatable.h +++ b/src/relocatable.h @@ -1,14 +1,12 @@ #ifndef RELOCATABLE_H #define RELOCATABLE_H -typedef struct relocatable -{ +typedef struct relocatable { unsigned int segment_index; unsigned int offset; } relocatable; -typedef union maybe_relocatable -{ +typedef union maybe_relocatable { struct relocatable relocatable; unsigned int felt; // TODO use a felt type } maybe_relocatable; diff --git a/src/run_context.h b/src/run_context.h index a4718aa..c6fd35a 100644 --- a/src/run_context.h +++ b/src/run_context.h @@ -3,8 +3,7 @@ #include "relocatable.h" -typedef struct run_context -{ +typedef struct run_context { relocatable pc; relocatable ap; relocatable fp; diff --git a/src/vm.c b/src/vm.c index fd2c108..485263b 100644 --- a/src/vm.c +++ b/src/vm.c @@ -1,8 +1,7 @@ #include "vm.h" #include "memory.h" -virtual_machine vm_new(void) -{ +virtual_machine vm_new(void) { virtual_machine vm = {{{0, 0}, {0, 0}, {0, 0}}, memory_new()}; return vm; } diff --git a/src/vm.h b/src/vm.h index 7eaa516..b24470c 100644 --- a/src/vm.h +++ b/src/vm.h @@ -3,8 +3,7 @@ #include "memory.h" #include "run_context.h" -typedef struct virtual_machine -{ +typedef struct virtual_machine { run_context run_context; memory memory; } virtual_machine; diff --git a/test/memory_tests.c b/test/memory_tests.c index 5f6cc52..ad1cb14 100644 --- a/test/memory_tests.c +++ b/test/memory_tests.c @@ -2,39 +2,38 @@ #include void load_data_one_element(void) { - // Initialize memory - memory mem = memory_new(); - memory_add_segment(&mem); - //Initialize data to load - struct CList *data = CList_init(sizeof(maybe_relocatable)); - union maybe_relocatable elem = {.felt = 1}; - data->add(data, &elem); - relocatable ptr = {0,0}; - // Load data - memory_load_data(&mem, ptr, data); - // Check memory - assert(mem.data->count(mem.data) == 1); - maybe_relocatable * first_elem = mem.data->at(mem.data, 0); - assert( first_elem->felt == 1); + // Initialize memory + memory mem = memory_new(); + memory_add_segment(&mem); + // Initialize data to load + struct CList *data = CList_init(sizeof(maybe_relocatable)); + union maybe_relocatable elem = {.felt = 1}; + data->add(data, &elem); + relocatable ptr = {0, 0}; + // Load data + memory_load_data(&mem, ptr, data); + // Check memory + assert(mem.data->count(mem.data) == 1); + maybe_relocatable *first_elem = mem.data->at(mem.data, 0); + assert(first_elem->felt == 1); } void load_data_empty(void) { - // Initialize memory - memory mem = memory_new(); - memory_add_segment(&mem); - //Initialize data to load - struct CList *data = CList_init(sizeof(maybe_relocatable)); - relocatable ptr = {0,0}; - // Load data - memory_load_data(&mem, ptr, data); - // Check memory - assert(mem.data->count(mem.data) == 1); - maybe_relocatable * first_elem = mem.data->at(mem.data, 0); - assert( first_elem->felt == 1); + // Initialize memory + memory mem = memory_new(); + memory_add_segment(&mem); + // Initialize data to load + struct CList *data = CList_init(sizeof(maybe_relocatable)); + relocatable ptr = {0, 0}; + // Load data + memory_load_data(&mem, ptr, data); + // Check memory + assert(mem.data->count(mem.data) == 1); + maybe_relocatable *first_elem = mem.data->at(mem.data, 0); + assert(first_elem->felt == 1); } -void memory_tests(void) -{ +void memory_tests(void) { printf("--------------------------------- \n"); printf("Test: load_data_one_element \n"); load_data_one_element(); diff --git a/test/runner_tests.c b/test/runner_tests.c index f2c7a94..9c1054a 100644 --- a/test/runner_tests.c +++ b/test/runner_tests.c @@ -1,41 +1,38 @@ #include "runner_tests.h" #include "clist.h" #include "memory.h" -#include "run_context.h" #include "program.h" +#include "run_context.h" #include "vm.h" #include #include -void initialize_runner_no_builtins_no_proof_mode_empty_program(void) -{ +void initialize_runner_no_builtins_no_proof_mode_empty_program(void) { struct CList *program_data = CList_init(sizeof(maybe_relocatable)); struct program program = {0, program_data}; cairo_runner runner = runner_new(program); runner_initialize(&runner); - // Check runner data - assert(runner.program_base.segment_index == 0 && runner.program_base.offset == 0); - assert(runner.execution_base.segment_index == 1 && runner.execution_base.offset == 0); - assert(runner.initial_pc.segment_index == 0 && runner.initial_pc.offset == 0); - assert(runner.initial_fp.segment_index == 1 && runner.initial_fp.offset == 2); - assert(runner.final_pc.segment_index == 3 && runner.final_pc.offset == 0); - // Check vm data - run_context run_context = runner.vm.run_context; - assert(run_context.pc.segment_index == 0 && run_context.pc.offset == 0); - assert(run_context.ap.segment_index == 1 && run_context.ap.offset == 2); - assert(run_context.fp.segment_index == 1 && run_context.fp.offset == 2); - // Check memory - memory memory = runner.vm.memory; - assert(memory.num_segments == 4); - assert(memory.data->count(memory.data) == 4); - // check individual segments - struct CList * segment_0 = memory.data->at(memory.data, 0); - assert(segment_0->count(segment_0) == 0); - + // Check runner data + assert(runner.program_base.segment_index == 0 && runner.program_base.offset == 0); + assert(runner.execution_base.segment_index == 1 && runner.execution_base.offset == 0); + assert(runner.initial_pc.segment_index == 0 && runner.initial_pc.offset == 0); + assert(runner.initial_fp.segment_index == 1 && runner.initial_fp.offset == 2); + assert(runner.final_pc.segment_index == 3 && runner.final_pc.offset == 0); + // Check vm data + run_context run_context = runner.vm.run_context; + assert(run_context.pc.segment_index == 0 && run_context.pc.offset == 0); + assert(run_context.ap.segment_index == 1 && run_context.ap.offset == 2); + assert(run_context.fp.segment_index == 1 && run_context.fp.offset == 2); + // Check memory + memory memory = runner.vm.memory; + assert(memory.num_segments == 4); + assert(memory.data->count(memory.data) == 4); + // check individual segments + struct CList *segment_0 = memory.data->at(memory.data, 0); + assert(segment_0->count(segment_0) == 0); } -void runner_tests(void) -{ +void runner_tests(void) { printf("--------------------------------- \n"); printf("Test: initialize_runner_no_builtins_no_proof_mode_empty_program \n"); initialize_runner_no_builtins_no_proof_mode_empty_program(); diff --git a/test/test.c b/test/test.c index d4da36d..8d5874b 100644 --- a/test/test.c +++ b/test/test.c @@ -1,9 +1,9 @@ +#include "decoder_test.h" +#include "memory.h" #include "memory_tests.h" #include "runner_tests.h" -#include "memory.h" #include #include -#include "decoder_test.h" int main(__attribute__((unused)) int argc, __attribute__((unused)) char **argv) { decoding_tests(); From 2c5b7d6d4595e21e329a5b835a1d896e14eaa51b Mon Sep 17 00:00:00 2001 From: Federica Date: Tue, 18 Jul 2023 12:20:09 -0300 Subject: [PATCH 09/59] Implement memory_insert --- src/memory.c | 22 ++++++++++++++++++++++ src/relocatable.h | 5 +++++ 2 files changed, 27 insertions(+) diff --git a/src/memory.c b/src/memory.c index c2b8161..cc5a811 100644 --- a/src/memory.c +++ b/src/memory.c @@ -23,6 +23,28 @@ ResultMemory memory_get(memory *mem, relocatable ptr) { return ok; } +ResultMemory memory_insert(memory *mem, relocatable ptr, maybe_relocatable value) { + if (ptr.segment_index > mem->data->count(mem->data)) { + ResultMemory error = {.is_error = true, .value = {.error = Insert}}; + return error; + } + CList *segment = mem->data->at(mem->data, ptr.segment_index); + ResultMemory get_result = memory_get(mem, ptr); + // Check for possible ovewrites + if (!get_result.is_error) { + if (maybe_relocatable_equal(get_result.value.memory_value, value)) { + ResultMemory ok = {.is_error = false, .value = {.none = 0}}; + return ok; + } else { + ResultMemory error = {.is_error = true, .value = {.error = Insert}}; + return error; + } + } + segment->insert(segment, &value, ptr.offset); + ResultMemory ok = {.is_error = false, .value = {.none = 0}}; + return ok; +} + relocatable memory_add_segment(memory *memory) { relocatable rel = {memory->num_segments, 0}; struct CList *segment = CList_init(sizeof(maybe_relocatable)); diff --git a/src/relocatable.h b/src/relocatable.h index b1324e2..29d686d 100644 --- a/src/relocatable.h +++ b/src/relocatable.h @@ -11,4 +11,9 @@ typedef union maybe_relocatable { unsigned int felt; // TODO use a felt type } maybe_relocatable; +bool maybe_relocatable_equal(maybe_relocatable a, maybe_relocatable b) { + return a.felt == b.felt && a.relocatable.segment_index == b.relocatable.segment_index && + a.relocatable.offset == b.relocatable.offset; +} + #endif From d62a3384c379f717e97c912347a36533710b728a Mon Sep 17 00:00:00 2001 From: Federica Date: Tue, 18 Jul 2023 13:39:44 -0300 Subject: [PATCH 10/59] fixes' --- src/memory.c | 9 ++++++--- src/memory.h | 16 ++++++++++------ src/relocatable.h | 7 +++---- test/memory_tests.c | 8 ++++++-- 4 files changed, 25 insertions(+), 15 deletions(-) diff --git a/src/memory.c b/src/memory.c index cc5a811..7a8b4e7 100644 --- a/src/memory.c +++ b/src/memory.c @@ -9,12 +9,14 @@ memory memory_new(void) { } ResultMemory memory_get(memory *mem, relocatable ptr) { - if (ptr.segment_index > mem->data->count(mem->data)) { + int index = ptr.segment_index; + int offset = ptr.offset; + if (index > mem->data->count(mem->data)) { ResultMemory error = {.is_error = true, .value = {.error = Get}}; return error; } CList *segment = mem->data->at(mem->data, ptr.segment_index); - if (ptr.offset > segment->count(segment)) { + if (offset > segment->count(segment)) { ResultMemory error = {.is_error = true, .value = {.error = Get}}; return error; } @@ -24,7 +26,8 @@ ResultMemory memory_get(memory *mem, relocatable ptr) { } ResultMemory memory_insert(memory *mem, relocatable ptr, maybe_relocatable value) { - if (ptr.segment_index > mem->data->count(mem->data)) { + int index = ptr.segment_index; + if (index > mem->data->count(mem->data)) { ResultMemory error = {.is_error = true, .value = {.error = Insert}}; return error; } diff --git a/src/memory.h b/src/memory.h index 1f7eaec..3bf9093 100644 --- a/src/memory.h +++ b/src/memory.h @@ -10,12 +10,6 @@ typedef struct memory { CList *data; } memory; -memory memory_new(void); - -relocatable memory_add_segment(memory *memory); - -relocatable memory_load_data(memory *memory, relocatable ptr, CList *data); - // Error handling enum MemoryError { @@ -36,4 +30,14 @@ typedef struct ResultMemory { union ResultMemoryValue value; } ResultMemory; +memory memory_new(void); + +ResultMemory memory_get(memory *mem, relocatable ptr); + +ResultMemory memory_insert(memory *mem, relocatable ptr, maybe_relocatable value); + +relocatable memory_add_segment(memory *memory); + +relocatable memory_load_data(memory *memory, relocatable ptr, CList *data); + #endif diff --git a/src/relocatable.h b/src/relocatable.h index 29d686d..95b6974 100644 --- a/src/relocatable.h +++ b/src/relocatable.h @@ -1,6 +1,8 @@ #ifndef RELOCATABLE_H #define RELOCATABLE_H +#include + typedef struct relocatable { unsigned int segment_index; unsigned int offset; @@ -11,9 +13,6 @@ typedef union maybe_relocatable { unsigned int felt; // TODO use a felt type } maybe_relocatable; -bool maybe_relocatable_equal(maybe_relocatable a, maybe_relocatable b) { - return a.felt == b.felt && a.relocatable.segment_index == b.relocatable.segment_index && - a.relocatable.offset == b.relocatable.offset; -} +bool maybe_relocatable_equal(maybe_relocatable a, maybe_relocatable b); #endif diff --git a/test/memory_tests.c b/test/memory_tests.c index ad1cb14..88bea5f 100644 --- a/test/memory_tests.c +++ b/test/memory_tests.c @@ -1,4 +1,6 @@ #include "memory_tests.h" +#include "relocatable.h" +#include #include void load_data_one_element(void) { @@ -14,8 +16,10 @@ void load_data_one_element(void) { memory_load_data(&mem, ptr, data); // Check memory assert(mem.data->count(mem.data) == 1); - maybe_relocatable *first_elem = mem.data->at(mem.data, 0); - assert(first_elem->felt == 1); + ResultMemory result = memory_get(&mem, ptr); + assert(!result.is_error); + assert(maybe_relocatable_equal(result.value.memory_value, elem)); + printf("OK!\n"); } void load_data_empty(void) { From 58a601e1a2715ff8eeec93fdabf2196cbb57b60c Mon Sep 17 00:00:00 2001 From: Milton Date: Wed, 19 Jul 2023 09:26:19 -0300 Subject: [PATCH 11/59] Merge main --- .github/workflows/ci.yml | 6 +- Makefile | 20 +-- README.md | 4 +- docs/rust-integration.md | 51 +++++++ lambdaworks/lib/.gitignore | 2 + lambdaworks/lib/lambdaworks.h | 28 ++++ lambdaworks/lib/lambdaworks/.gitignore | 19 +++ lambdaworks/lib/lambdaworks/Cargo.toml | 13 ++ lambdaworks/lib/lambdaworks/src/lib.rs | 73 ++++++++++ test/felt_test.c | 176 +++++++++++++++++++++++++ test/felt_test.h | 9 ++ test/test.c | 2 + 12 files changed, 391 insertions(+), 12 deletions(-) create mode 100644 docs/rust-integration.md create mode 100644 lambdaworks/lib/.gitignore create mode 100644 lambdaworks/lib/lambdaworks.h create mode 100644 lambdaworks/lib/lambdaworks/.gitignore create mode 100644 lambdaworks/lib/lambdaworks/Cargo.toml create mode 100644 lambdaworks/lib/lambdaworks/src/lib.rs create mode 100644 test/felt_test.c create mode 100644 test/felt_test.h diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f8b21b9..b47193a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,8 +9,10 @@ jobs: tests_and_format: runs-on: ubuntu-latest steps: + - uses: dtolnay/rust-toolchain@1.70.0 - uses: actions/checkout@v3 - run: make check_fmt - - run: make test + - run: LD_LIBRARY_PATH=${PWD}/lambdaworks/lib/lambdaworks/target/release make test - run: sudo apt install valgrind -y - - run: make SANITIZER_FLAGS= valgrind + - run: make compile-rust + # - run: make SANITIZER_FLAGS= LN_FLAGS="-L${PWD}/lambdaworks/lib/lambdaworks/target/release/ -static -llambdaworks" valgrind diff --git a/Makefile b/Makefile index 2b9b187..b695a69 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: clean fmt check_fmt valgrind +.PHONY: clean fmt check_fmt valgrind compile-rust deps-macos TARGET=cairo_vm TEST_TARGET=cairo_vm_test @@ -7,7 +7,7 @@ CC=cc SANITIZER_FLAGS=-fsanitize=address -fno-omit-frame-pointer CFLAGS=-std=c11 -Wall -Wextra -Wimplicit-fallthrough -Werror -pedantic -g -O0 CFLAGS_TEST=-I./src -LN_FLAGS= +LN_FLAGS=-L./lambdaworks/lib/lambdaworks/target/release/ -llambdaworks BUILD_DIR=./build SRC_DIR=./src @@ -25,7 +25,7 @@ TEST_OBJECTS = $(patsubst $(TEST_DIR)/%.c, $(BUILD_DIR)/%.o, $(TEST_SOURCE)) # Gcc/Clang will create these .d files containing dependencies. DEP = $(OBJECTS:%.o=%.d) -default: $(TARGET) +default: compile-rust $(TARGET) $(TARGET): $(BUILD_DIR)/$(TARGET) @@ -35,7 +35,7 @@ $(BUILD_DIR)/$(TARGET): $(OBJECTS) $(TEST_TARGET): $(BUILD_DIR)/$(TEST_TARGET) $(BUILD_DIR)/$(TEST_TARGET): $(TEST_OBJECTS) - $(CC) $(CFLAGS) $(CFLAGS_TEST) $(SANITIZER_FLAGS) $^ -o $@ + $(CC) $(CFLAGS) $(CFLAGS_TEST) $(SANITIZER_FLAGS) $(LN_FLAGS) $^ -o $@ -include $(DEP) @@ -54,14 +54,15 @@ $(BUILD_DIR)/%.o: $(TEST_DIR)/%.c deps-macos: brew install clang-format -run: $(TARGET) - $(BUILD_DIR)/$(TARGET) +run: default + $(BUILD_DIR)/$(TARGET) -test: $(TEST_TARGET) +test: compile-rust $(TEST_TARGET) $(BUILD_DIR)/$(TEST_TARGET) clean: - rm -rf $(BUILD_DIR) + rm -rf $(BUILD_DIR) && \ + cd lambdaworks/lib/lambdaworks && cargo clean fmt: clang-format --style=file -i $(SOURCE) $(TEST_SOURCE) $(HEADERS) $(TEST_HEADERS) @@ -71,3 +72,6 @@ check_fmt: valgrind: clean test valgrind --leak-check=full --show-reachable=yes --show-leak-kinds=all --track-origins=yes --error-exitcode=1 ./build/cairo_vm_test + +compile-rust: + cd lambdaworks/lib/lambdaworks && cargo build --release diff --git a/README.md b/README.md index 4ea80a3..89f0b67 100644 --- a/README.md +++ b/README.md @@ -8,8 +8,8 @@ This is a work in progress implementation of the [Cairo VM](https://github.com/l ## Requirements - A working C compiler with `C11` support. - -- clang-format installed in the system. +- `clang-format` installed in the system. +- [Rust](https://www.rust-lang.org/tools/install) ## Local development diff --git a/docs/rust-integration.md b/docs/rust-integration.md new file mode 100644 index 0000000..230cdad --- /dev/null +++ b/docs/rust-integration.md @@ -0,0 +1,51 @@ +# Lambdaworks wrapper + +For now, this is a mock containing only a "number" function that always return 42. It's a +proof of concept of a go package that integrates with a rust library. + +## Package structure + +These are the relevant files: + +``` +./lambdaworks: + └── lib: directory with the rust and C code. + ├── lambdaworks.h: C headers representing the functions + │ + └── lambdaworks: Rust package. + ├── Cargo.Toml: Rust package definition. + └── src/lib.rs: rust library. +``` + +## Compiling + +The rust package can be compiled by moving to the `lib/lambdaworks` directory and executing `cargo build --release`. This produces a `lib/lambdaworks/target/liblambdaworks.a`. + +In `Makefile` we can see that one of the steps is actually moving to the rust project, compiling, and then copying the archive file to the `lib` directory so it can be consumed by the go code. + +## FFI + +FFI is a way of having calls between C and rust. To allow this we have two key steps: +- Wrapping function calls (with `no_mangle`` modifier) and adding a header file to make them available to C. +- Making sure that all data structures can be represented in C. + +`lambdaworks.h` is the file containing all of the function wrappers around the field element type. As FieldElement and all its variants are already defined in lambdaworks and do not conform +to the C memory layout we need to have our own representation with the `repr(C)` modifier. +Internally, field elements are represented by an array of four integers called "limbs", using +montgomery representation, and do not contain any extra data. For simplicity, we then choose to +represent them in C as that array, and `felt_t` is just an alias for an unsigned 64 bit integer array with four elements. + +As we can't return arrays in C, any rust function that returns a felt (one, zero, from, mul, add, etc) has a `result` with a raw pointer that is written instead. Memory allocation can happen +statically in C, as they will always be 4-element arrays. + +`lib.rs` mostly does, for every wrapper function: +- Convert argument felts (limb arrays) to rust felts. +- Call the wrapped operation +- Convert the result back to limbs representation in the result parameter. + +## Limbs representation + +We need to take into account that we take the `felt.representative()` limbs instead of `felt.value().limbs` version, as the latter is in montgomery representation. If we took that one +instead, when building the `UnsignedInteger<4> struct` we'll be representing a different number. +When constructiong the `FieldElement` from that, the montgomery algorithm will be applied even if the data is already in that representation, effectively building a Felt that represents a different number. + diff --git a/lambdaworks/lib/.gitignore b/lambdaworks/lib/.gitignore new file mode 100644 index 0000000..7b782dd --- /dev/null +++ b/lambdaworks/lib/.gitignore @@ -0,0 +1,2 @@ +liblambdaworks.a +liblambdaworks.so diff --git a/lambdaworks/lib/lambdaworks.h b/lambdaworks/lib/lambdaworks.h new file mode 100644 index 0000000..bc3c7b5 --- /dev/null +++ b/lambdaworks/lib/lambdaworks.h @@ -0,0 +1,28 @@ +#include + +/* A single limb (unsigned integer with 64 bits). */ +typedef uint64_t limb_t; + +/* A 256 bit prime field element (felt), represented as four limbs (integers). */ +typedef limb_t felt_t[4]; + +/* Gets a felt_t representing the "value" number, in montgomery format. */ +void from(felt_t result, uint64_t value); + +/* Gets a felt_t representing 0 */ +void zero(felt_t result); + +/* Gets a felt_t representing 1 */ +void one(felt_t result); + +/* Writes the result variable with the sum of a and b felts. */ +void add(felt_t a, felt_t b, felt_t result); + +/* Writes the result variable with a - b. */ +void sub(felt_t a, felt_t b, felt_t result); + +/* Writes the result variable with a * b. */ +void mul(felt_t a, felt_t b, felt_t result); + +/* Writes the result variable with a / b. */ +void div(felt_t a, felt_t b, felt_t result); diff --git a/lambdaworks/lib/lambdaworks/.gitignore b/lambdaworks/lib/lambdaworks/.gitignore new file mode 100644 index 0000000..196e176 --- /dev/null +++ b/lambdaworks/lib/lambdaworks/.gitignore @@ -0,0 +1,19 @@ +# Generated by Cargo +# will have compiled files and executables +debug/ +target/ + +# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries +# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html +Cargo.lock + +# These are backup files generated by rustfmt +**/*.rs.bk + +# MSVC Windows builds of rustc generate these, which store debugging information +*.pdb + + +# Added by cargo + +/target diff --git a/lambdaworks/lib/lambdaworks/Cargo.toml b/lambdaworks/lib/lambdaworks/Cargo.toml new file mode 100644 index 0000000..f2e0655 --- /dev/null +++ b/lambdaworks/lib/lambdaworks/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "lambdaworks" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +libc = "0.2" +lambdaworks-math = { git = "https://github.com/lambdaclass/lambdaworks.git" } + +[lib] +crate-type = ["cdylib", "staticlib", "lib"] diff --git a/lambdaworks/lib/lambdaworks/src/lib.rs b/lambdaworks/lib/lambdaworks/src/lib.rs new file mode 100644 index 0000000..35af041 --- /dev/null +++ b/lambdaworks/lib/lambdaworks/src/lib.rs @@ -0,0 +1,73 @@ +use lambdaworks_math::{ + field::element::FieldElement, + field::fields::fft_friendly::stark_252_prime_field::Stark252PrimeField, + unsigned_integer::element::UnsignedInteger, +}; + +// A 256 bit prime field represented as a Montgomery, 4-limb UnsignedInteger. +type Felt = FieldElement; + +// C representation of a limbs array: a raw pointer to a mutable unsigned 64 bits integer. +type Limbs = *mut u64; + +// Receives a Felt and writes its C representation in the limbs variable, as we can't +// return arrays in C. +// +// Felt uses the montgomery representation internally, so to be able to reconstruct a felt +// in a different call, the representative limbs are the ones written as a result of this call. +fn felt_to_limbs(felt: Felt, limbs: Limbs) { + let representative = felt.representative().limbs; + for i in 0..4 { + let u = i as usize; + unsafe { + *limbs.offset(i) = representative[u]; + } + } +} + +// Receives a C representation of a limbs array and returns a felt representing +// the same number. +fn limbs_to_felt(limbs: Limbs) -> Felt { + unsafe { + let slice: &mut [u64] = std::slice::from_raw_parts_mut(limbs, 4); + let array: [u64; 4] = slice.try_into().unwrap(); + let ui = UnsignedInteger::from_limbs(array); + let felt = Felt::from(&ui); + return felt; + } +} + +#[no_mangle] +pub extern "C" fn from(result: Limbs, value: u64) { + felt_to_limbs(Felt::from(value), result); +} + +#[no_mangle] +pub extern "C" fn zero(result: Limbs) { + felt_to_limbs(Felt::zero(), result) +} + +#[no_mangle] +pub extern "C" fn one(result: Limbs) { + felt_to_limbs(Felt::one(), result) +} + +#[no_mangle] +pub extern "C" fn add(a: Limbs, b: Limbs, result: Limbs) { + felt_to_limbs(limbs_to_felt(a) + limbs_to_felt(b), result); +} + +#[no_mangle] +pub extern "C" fn sub(a: Limbs, b: Limbs, result: Limbs) { + felt_to_limbs(limbs_to_felt(a) - limbs_to_felt(b), result) +} + +#[no_mangle] +pub extern "C" fn mul(a: Limbs, b: Limbs, result: Limbs) { + felt_to_limbs(limbs_to_felt(a) * limbs_to_felt(b), result) +} + +#[no_mangle] +pub extern "C" fn div(a: Limbs, b: Limbs, result: Limbs) { + felt_to_limbs(limbs_to_felt(a) / limbs_to_felt(b), result) +} diff --git a/test/felt_test.c b/test/felt_test.c new file mode 100644 index 0000000..0be1879 --- /dev/null +++ b/test/felt_test.c @@ -0,0 +1,176 @@ +#include "felt_test.h" + +void felt_sub(void) { + felt_t f_one; + one(f_one); + + felt_t expected; + felt_t result; + zero(expected); + + sub(f_one, f_one, result); + assert(expected[0] == result[0]); + assert(expected[1] == result[1]); + assert(expected[2] == result[2]); + assert(expected[3] == result[3]); +} + +void felt_add(void) { + felt_t f_one; + one(f_one); + + felt_t f_zero; + zero(f_zero); + + felt_t expected; + one(expected); + + felt_t result; + add(f_one, f_zero, result); + assert(expected[0] == result[0]); + assert(expected[1] == result[1]); + assert(expected[2] == result[2]); + assert(expected[3] == result[3]); +} + +void felt_mul1(void) { + felt_t f_one; + one(f_one); + + felt_t expected; + one(expected); + + felt_t result; + mul(f_one, f_one, result); + assert(expected[0] == result[0]); + assert(expected[1] == result[1]); + assert(expected[2] == result[2]); + assert(expected[3] == result[3]); +} + +void felt_mul0(void) { + felt_t f_one; + one(f_one); + + felt_t f_zero; + zero(f_zero); + + felt_t expected; + zero(expected); + + felt_t result; + mul(f_one, f_zero, result); + assert(expected[0] == result[0]); + assert(expected[1] == result[1]); + assert(expected[2] == result[2]); + assert(expected[3] == result[3]); +} + +void felt_mul9(void) { + felt_t f_three; + from(f_three, 3); + + felt_t expected; + from(expected, 9); + + felt_t result; + mul(f_three, f_three, result); + assert(expected[0] == result[0]); + assert(expected[1] == result[1]); + assert(expected[2] == result[2]); + assert(expected[3] == result[3]); +} + +void felt_div3(void) { + felt_t f_three; + from(f_three, 3); + + felt_t expected; + from(expected, 1); + + felt_t result; + div(f_three, f_three, result); + assert(expected[0] == result[0]); + assert(expected[1] == result[1]); + assert(expected[2] == result[2]); + assert(expected[3] == result[3]); +} + +void felt_div4(void) { + felt_t f_four; + from(f_four, 4); + + felt_t f_two; + from(f_two, 2); + + felt_t expected; + from(expected, 2); + + felt_t result; + div(f_four, f_two, result); + assert(expected[0] == result[0]); + assert(expected[1] == result[1]); + assert(expected[2] == result[2]); + assert(expected[3] == result[3]); +} + +void felt_div4_err(void) { + felt_t f_four; + from(f_four, 4); + + felt_t f_one; + from(f_one, 1); + + felt_t expected; + from(expected, 45); + + felt_t result; + div(f_four, f_one, result); + + assert(expected[0] == result[0]); + assert(expected[1] == result[1]); + assert(expected[2] == result[2]); + assert(expected[3] != result[3]); +} + +void felt_tests(void) { + printf("----------------------\n"); + printf("Test: Substraction\n"); + felt_sub(); + printf("OK!\n"); + + printf("----------------------\n"); + printf("Test: Addition\n"); + felt_add(); + printf("OK!\n"); + + printf("----------------------\n"); + printf("Test: Multiplication\n"); + felt_mul1(); + printf("OK!\n"); + + printf("----------------------\n"); + printf("Test: Multiplication0\n"); + felt_mul0(); + printf("OK!\n"); + + printf("----------------------\n"); + printf("Test: Multiplication9\n"); + felt_mul9(); + printf("OK!\n"); + + printf("----------------------\n"); + printf("Test: Divition3\n"); + felt_div3(); + printf("OK!\n"); + + printf("----------------------\n"); + printf("Test: Divition4\n"); + felt_div4(); + printf("OK!\n"); + + printf("----------------------\n"); + printf("Test: Divition error\n"); + felt_div4_err(); + printf("OK!\n"); +} diff --git a/test/felt_test.h b/test/felt_test.h new file mode 100644 index 0000000..126ecbe --- /dev/null +++ b/test/felt_test.h @@ -0,0 +1,9 @@ +#ifndef FELT_H +#define FELT_H +#include "../lambdaworks/lib/lambdaworks.h" +#include +#include + +void felt_tests(void); + +#endif diff --git a/test/test.c b/test/test.c index 8d5874b..3d0b67a 100644 --- a/test/test.c +++ b/test/test.c @@ -2,10 +2,12 @@ #include "memory.h" #include "memory_tests.h" #include "runner_tests.h" +#include "felt_test.h" #include #include int main(__attribute__((unused)) int argc, __attribute__((unused)) char **argv) { + felt_tests(); decoding_tests(); memory_tests(); return 0; From 863746507232b1a194a03b3d16164d40d4a75fad Mon Sep 17 00:00:00 2001 From: Milton Date: Wed, 19 Jul 2023 09:26:42 -0300 Subject: [PATCH 12/59] fix format --- test/memory_tests.c | 6 +++--- test/test.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/test/memory_tests.c b/test/memory_tests.c index 88bea5f..d8f3294 100644 --- a/test/memory_tests.c +++ b/test/memory_tests.c @@ -17,9 +17,9 @@ void load_data_one_element(void) { // Check memory assert(mem.data->count(mem.data) == 1); ResultMemory result = memory_get(&mem, ptr); - assert(!result.is_error); - assert(maybe_relocatable_equal(result.value.memory_value, elem)); - printf("OK!\n"); + assert(!result.is_error); + assert(maybe_relocatable_equal(result.value.memory_value, elem)); + printf("OK!\n"); } void load_data_empty(void) { diff --git a/test/test.c b/test/test.c index 3d0b67a..89af95c 100644 --- a/test/test.c +++ b/test/test.c @@ -1,8 +1,8 @@ #include "decoder_test.h" +#include "felt_test.h" #include "memory.h" #include "memory_tests.h" #include "runner_tests.h" -#include "felt_test.h" #include #include From 1ae32e5c5f44ff010d31aff6920e501b45a90482 Mon Sep 17 00:00:00 2001 From: Federica Date: Wed, 19 Jul 2023 10:17:34 -0300 Subject: [PATCH 13/59] Add file --- src/relocatable.c | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 src/relocatable.c diff --git a/src/relocatable.c b/src/relocatable.c new file mode 100644 index 0000000..305e92d --- /dev/null +++ b/src/relocatable.c @@ -0,0 +1,6 @@ +#include "relocatable.h" + +bool maybe_relocatable_equal(maybe_relocatable a, maybe_relocatable b) { + return a.felt == b.felt && a.relocatable.segment_index == b.relocatable.segment_index && + a.relocatable.offset == b.relocatable.offset; +} From 44f91eb98c05254c3981ce20ddd924fbe939970a Mon Sep 17 00:00:00 2001 From: Federica Date: Wed, 19 Jul 2023 10:22:32 -0300 Subject: [PATCH 14/59] Finish load_data tests --- test/memory_tests.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/test/memory_tests.c b/test/memory_tests.c index 88bea5f..ccb9148 100644 --- a/test/memory_tests.c +++ b/test/memory_tests.c @@ -13,13 +13,14 @@ void load_data_one_element(void) { data->add(data, &elem); relocatable ptr = {0, 0}; // Load data - memory_load_data(&mem, ptr, data); + relocatable end_ptr = memory_load_data(&mem, ptr, data); + assert(end_ptr.segment_index == 0 && end_ptr.offset == 1); // Check memory assert(mem.data->count(mem.data) == 1); ResultMemory result = memory_get(&mem, ptr); - assert(!result.is_error); - assert(maybe_relocatable_equal(result.value.memory_value, elem)); - printf("OK!\n"); + assert(!result.is_error); + assert(maybe_relocatable_equal(result.value.memory_value, elem)); + printf("OK!\n"); } void load_data_empty(void) { @@ -30,14 +31,17 @@ void load_data_empty(void) { struct CList *data = CList_init(sizeof(maybe_relocatable)); relocatable ptr = {0, 0}; // Load data - memory_load_data(&mem, ptr, data); + relocatable end_ptr = memory_load_data(&mem, ptr, data); + assert(end_ptr.segment_index == 0 && end_ptr.offset == 1); // Check memory - assert(mem.data->count(mem.data) == 1); - maybe_relocatable *first_elem = mem.data->at(mem.data, 0); - assert(first_elem->felt == 1); + assert(mem.data->count(mem.data) == 0); + printf("OK!\n"); } void memory_tests(void) { + printf("--------------------------------- \n"); + printf("Test: load_data_empty \n"); + load_data_one_element(); printf("--------------------------------- \n"); printf("Test: load_data_one_element \n"); load_data_one_element(); From 9b83d6df11643751a3ec8f15ec9e239811c7c21c Mon Sep 17 00:00:00 2001 From: Federica Date: Wed, 19 Jul 2023 10:27:40 -0300 Subject: [PATCH 15/59] Fix bug --- src/memory.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/memory.c b/src/memory.c index 7a8b4e7..6399ac4 100644 --- a/src/memory.c +++ b/src/memory.c @@ -11,7 +11,7 @@ memory memory_new(void) { ResultMemory memory_get(memory *mem, relocatable ptr) { int index = ptr.segment_index; int offset = ptr.offset; - if (index > mem->data->count(mem->data)) { + if (index >= mem->data->count(mem->data)) { ResultMemory error = {.is_error = true, .value = {.error = Get}}; return error; } From 0bdf1e1778fd56a2b1fd17e4208af7fc75b91cce Mon Sep 17 00:00:00 2001 From: Federica Date: Wed, 19 Jul 2023 10:58:23 -0300 Subject: [PATCH 16/59] Fix bug --- src/memory.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/memory.c b/src/memory.c index 6399ac4..ef1e9fa 100644 --- a/src/memory.c +++ b/src/memory.c @@ -16,7 +16,7 @@ ResultMemory memory_get(memory *mem, relocatable ptr) { return error; } CList *segment = mem->data->at(mem->data, ptr.segment_index); - if (offset > segment->count(segment)) { + if (offset >= segment->count(segment)) { ResultMemory error = {.is_error = true, .value = {.error = Get}}; return error; } From 194d57084100c96a48b71220407bf1cbf0d1ae07 Mon Sep 17 00:00:00 2001 From: Milton Date: Wed, 19 Jul 2023 11:01:53 -0300 Subject: [PATCH 17/59] change to pointer --- src/memory.c | 4 ++-- src/relocatable.c | 4 +++- src/relocatable.h | 5 ++++- test/memory_tests.c | 4 +++- test/memory_tests.h | 2 ++ 5 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/memory.c b/src/memory.c index 7a8b4e7..ef1e9fa 100644 --- a/src/memory.c +++ b/src/memory.c @@ -11,12 +11,12 @@ memory memory_new(void) { ResultMemory memory_get(memory *mem, relocatable ptr) { int index = ptr.segment_index; int offset = ptr.offset; - if (index > mem->data->count(mem->data)) { + if (index >= mem->data->count(mem->data)) { ResultMemory error = {.is_error = true, .value = {.error = Get}}; return error; } CList *segment = mem->data->at(mem->data, ptr.segment_index); - if (offset > segment->count(segment)) { + if (offset >= segment->count(segment)) { ResultMemory error = {.is_error = true, .value = {.error = Get}}; return error; } diff --git a/src/relocatable.c b/src/relocatable.c index 305e92d..b0c48c8 100644 --- a/src/relocatable.c +++ b/src/relocatable.c @@ -1,6 +1,8 @@ #include "relocatable.h" +bool felt_equal(felt_t *a, felt_t *b) { return a[0] == b[0] && a[1] == b[1] && a[2] == b[2] && a[3] == b[3]; } + bool maybe_relocatable_equal(maybe_relocatable a, maybe_relocatable b) { - return a.felt == b.felt && a.relocatable.segment_index == b.relocatable.segment_index && + return felt_equal(a.felt, b.felt) && a.relocatable.segment_index == b.relocatable.segment_index && a.relocatable.offset == b.relocatable.offset; } diff --git a/src/relocatable.h b/src/relocatable.h index 95b6974..e4554b4 100644 --- a/src/relocatable.h +++ b/src/relocatable.h @@ -1,7 +1,9 @@ #ifndef RELOCATABLE_H #define RELOCATABLE_H +#include "../lambdaworks/lib/lambdaworks.h" #include +#include typedef struct relocatable { unsigned int segment_index; @@ -10,9 +12,10 @@ typedef struct relocatable { typedef union maybe_relocatable { struct relocatable relocatable; - unsigned int felt; // TODO use a felt type + felt_t *felt; } maybe_relocatable; +bool felt_equal(felt_t *a, felt_t *b); bool maybe_relocatable_equal(maybe_relocatable a, maybe_relocatable b); #endif diff --git a/test/memory_tests.c b/test/memory_tests.c index ccb9148..44c3940 100644 --- a/test/memory_tests.c +++ b/test/memory_tests.c @@ -9,7 +9,9 @@ void load_data_one_element(void) { memory_add_segment(&mem); // Initialize data to load struct CList *data = CList_init(sizeof(maybe_relocatable)); - union maybe_relocatable elem = {.felt = 1}; + felt_t f; + one(f); + maybe_relocatable elem = {.felt = &f}; data->add(data, &elem); relocatable ptr = {0, 0}; // Load data diff --git a/test/memory_tests.h b/test/memory_tests.h index 3765641..f955f15 100644 --- a/test/memory_tests.h +++ b/test/memory_tests.h @@ -1,5 +1,7 @@ #ifndef MEMORY_TEST_H #define MEMORY_TEST_H + +#include "../lambdaworks/lib/lambdaworks.h" #include "memory.h" #include #include From d193b3f18b3595894a83bb6e5ee1ef4764332aa9 Mon Sep 17 00:00:00 2001 From: Federica Date: Thu, 20 Jul 2023 04:54:58 -0300 Subject: [PATCH 18/59] Add boolean is_felt to maybe_relocatable type --- src/cairo_runner.c | 2 +- src/relocatable.c | 8 ++++++-- src/relocatable.h | 7 ++++++- test/memory_tests.c | 30 +++++++++++++++++++++--------- 4 files changed, 34 insertions(+), 13 deletions(-) diff --git a/src/cairo_runner.c b/src/cairo_runner.c index 197f380..04b04e9 100644 --- a/src/cairo_runner.c +++ b/src/cairo_runner.c @@ -37,7 +37,7 @@ relocatable runner_initialize_function_entrypoint(cairo_runner *runner, unsigned } relocatable runner_initialize_main_entrypoint(cairo_runner *runner) { - CList *stack = CList_init(sizeof(union maybe_relocatable)); + CList *stack = CList_init(sizeof(maybe_relocatable)); // Handle builtin initial stack // Handle proof-mode specific behaviour relocatable return_fp = memory_add_segment(&runner->vm.memory); diff --git a/src/relocatable.c b/src/relocatable.c index 305e92d..bc5beca 100644 --- a/src/relocatable.c +++ b/src/relocatable.c @@ -1,6 +1,10 @@ #include "relocatable.h" bool maybe_relocatable_equal(maybe_relocatable a, maybe_relocatable b) { - return a.felt == b.felt && a.relocatable.segment_index == b.relocatable.segment_index && - a.relocatable.offset == b.relocatable.offset; + if (a.is_felt && b.is_felt) { + return a.value.felt == b.value.felt; + } else if (!a.is_felt && !b.is_felt) { + return a.value.relocatable.segment_index == b.value.relocatable.segment_index && + a.value.relocatable.offset == b.value.relocatable.offset; + } } diff --git a/src/relocatable.h b/src/relocatable.h index 95b6974..21e931a 100644 --- a/src/relocatable.h +++ b/src/relocatable.h @@ -8,9 +8,14 @@ typedef struct relocatable { unsigned int offset; } relocatable; -typedef union maybe_relocatable { +union maybe_relocatable_value { struct relocatable relocatable; unsigned int felt; // TODO use a felt type +}; + +typedef struct maybe_relocatable { + union maybe_relocatable_value value; + bool is_felt; } maybe_relocatable; bool maybe_relocatable_equal(maybe_relocatable a, maybe_relocatable b); diff --git a/test/memory_tests.c b/test/memory_tests.c index ccb9148..72a31e9 100644 --- a/test/memory_tests.c +++ b/test/memory_tests.c @@ -3,7 +3,16 @@ #include #include -void load_data_one_element(void) { +void memory_get_err(void) { + // Initialize memory + memory mem = memory_new(); + relocatable ptr = {0, 0}; + ResultMemory result = memory_get(&mem, ptr); + assert(result.is_error); + assert(result.value.error == Get); +} + +void memory_load_data_one_element(void) { // Initialize memory memory mem = memory_new(); memory_add_segment(&mem); @@ -16,14 +25,13 @@ void load_data_one_element(void) { relocatable end_ptr = memory_load_data(&mem, ptr, data); assert(end_ptr.segment_index == 0 && end_ptr.offset == 1); // Check memory - assert(mem.data->count(mem.data) == 1); ResultMemory result = memory_get(&mem, ptr); assert(!result.is_error); assert(maybe_relocatable_equal(result.value.memory_value, elem)); printf("OK!\n"); } -void load_data_empty(void) { +void memory_load_data_empty(void) { // Initialize memory memory mem = memory_new(); memory_add_segment(&mem); @@ -32,17 +40,21 @@ void load_data_empty(void) { relocatable ptr = {0, 0}; // Load data relocatable end_ptr = memory_load_data(&mem, ptr, data); - assert(end_ptr.segment_index == 0 && end_ptr.offset == 1); + assert(end_ptr.segment_index == 0 && end_ptr.offset == 0); // Check memory - assert(mem.data->count(mem.data) == 0); + ResultMemory result = memory_get(&mem, ptr); + assert(result.is_error); printf("OK!\n"); } void memory_tests(void) { printf("--------------------------------- \n"); - printf("Test: load_data_empty \n"); - load_data_one_element(); + printf("Test: memory_get_err \n"); + memory_get_err(); + printf("--------------------------------- \n"); + printf("Test: memory_load_data_empty \n"); + memory_load_data_empty(); printf("--------------------------------- \n"); - printf("Test: load_data_one_element \n"); - load_data_one_element(); + printf("Test: memory_load_data_one_element \n"); + memory_load_data_one_element(); } From 1f439868483a5fd531daadb6bd42acaaa1a85698 Mon Sep 17 00:00:00 2001 From: Federica Date: Thu, 20 Jul 2023 04:57:27 -0300 Subject: [PATCH 19/59] Fixes --- src/relocatable.c | 2 ++ test/memory_tests.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/relocatable.c b/src/relocatable.c index bc5beca..b7121fb 100644 --- a/src/relocatable.c +++ b/src/relocatable.c @@ -6,5 +6,7 @@ bool maybe_relocatable_equal(maybe_relocatable a, maybe_relocatable b) { } else if (!a.is_felt && !b.is_felt) { return a.value.relocatable.segment_index == b.value.relocatable.segment_index && a.value.relocatable.offset == b.value.relocatable.offset; + } else { + return false; } } diff --git a/test/memory_tests.c b/test/memory_tests.c index 72a31e9..d4fcb76 100644 --- a/test/memory_tests.c +++ b/test/memory_tests.c @@ -18,7 +18,7 @@ void memory_load_data_one_element(void) { memory_add_segment(&mem); // Initialize data to load struct CList *data = CList_init(sizeof(maybe_relocatable)); - union maybe_relocatable elem = {.felt = 1}; + maybe_relocatable elem = {.is_felt = true, .value = {.felt = 1}}; data->add(data, &elem); relocatable ptr = {0, 0}; // Load data From 49805ee9eee6614b76b3f1145dd0490b195d4fe9 Mon Sep 17 00:00:00 2001 From: Federica Date: Thu, 20 Jul 2023 05:00:23 -0300 Subject: [PATCH 20/59] Add fix + test --- src/memory.c | 2 +- test/memory_tests.c | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/memory.c b/src/memory.c index ef1e9fa..80c5e65 100644 --- a/src/memory.c +++ b/src/memory.c @@ -27,7 +27,7 @@ ResultMemory memory_get(memory *mem, relocatable ptr) { ResultMemory memory_insert(memory *mem, relocatable ptr, maybe_relocatable value) { int index = ptr.segment_index; - if (index > mem->data->count(mem->data)) { + if (index >= mem->data->count(mem->data)) { ResultMemory error = {.is_error = true, .value = {.error = Insert}}; return error; } diff --git a/test/memory_tests.c b/test/memory_tests.c index d4fcb76..051c4da 100644 --- a/test/memory_tests.c +++ b/test/memory_tests.c @@ -12,6 +12,16 @@ void memory_get_err(void) { assert(result.value.error == Get); } +void memory_insert_err_unallocated_segement(void) { + // Initialize memory + memory mem = memory_new(); + relocatable ptr = {0, 0}; + maybe_relocatable elem = {.is_felt = true, .value = {.felt = 1}}; + ResultMemory result = memory_insert(&mem, ptr, elem); + assert(result.is_error); + assert(result.value.error == Insert); +} + void memory_load_data_one_element(void) { // Initialize memory memory mem = memory_new(); @@ -52,6 +62,9 @@ void memory_tests(void) { printf("Test: memory_get_err \n"); memory_get_err(); printf("--------------------------------- \n"); + printf("Test: memory_insert_err_unallocated_segement \n"); + memory_insert_err_unallocated_segement(); + printf("--------------------------------- \n"); printf("Test: memory_load_data_empty \n"); memory_load_data_empty(); printf("--------------------------------- \n"); From 4353f64349e1ba7a59f47865ed644e7edf514aa7 Mon Sep 17 00:00:00 2001 From: Federica Date: Thu, 20 Jul 2023 05:06:34 -0300 Subject: [PATCH 21/59] Add more tests --- test/memory_tests.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/test/memory_tests.c b/test/memory_tests.c index 051c4da..22927c1 100644 --- a/test/memory_tests.c +++ b/test/memory_tests.c @@ -10,6 +10,7 @@ void memory_get_err(void) { ResultMemory result = memory_get(&mem, ptr); assert(result.is_error); assert(result.value.error == Get); + printf("OK!\n"); } void memory_insert_err_unallocated_segement(void) { @@ -20,6 +21,36 @@ void memory_insert_err_unallocated_segement(void) { ResultMemory result = memory_insert(&mem, ptr, elem); assert(result.is_error); assert(result.value.error == Insert); + printf("OK!\n"); +} + +void memory_insert_err_ovewrite_attempt(void) { + // Initialize memory + memory mem = memory_new(); + memory_add_segment(&mem); + relocatable ptr = {0, 0}; + maybe_relocatable elem = {.is_felt = true, .value = {.felt = 1}}; + ResultMemory result = memory_insert(&mem, ptr, elem); + assert(!result.is_error); + maybe_relocatable elem_b = {.is_felt = true, .value = {.felt = 2}}; + ResultMemory result_b = memory_insert(&mem, ptr, elem_b); + assert(result_b.is_error); + assert(result_b.value.error == Insert); + printf("OK!\n"); +} + +void memory_insert_ok_ovewrite_same_value(void) { + // Initialize memory + memory mem = memory_new(); + memory_add_segment(&mem); + relocatable ptr = {0, 0}; + maybe_relocatable elem = {.is_felt = true, .value = {.felt = 1}}; + ResultMemory result = memory_insert(&mem, ptr, elem); + assert(!result.is_error); + maybe_relocatable elem_b = {.is_felt = true, .value = {.felt = 1}}; + ResultMemory result_b = memory_insert(&mem, ptr, elem_b); + assert(!result_b.is_error); + printf("OK!\n"); } void memory_load_data_one_element(void) { @@ -65,6 +96,12 @@ void memory_tests(void) { printf("Test: memory_insert_err_unallocated_segement \n"); memory_insert_err_unallocated_segement(); printf("--------------------------------- \n"); + printf("Test: memory_insert_err_ovewrite_attempt \n"); + memory_insert_err_ovewrite_attempt(); + printf("--------------------------------- \n"); + printf("Test: memory_insert_ok_ovewrite_same_value \n"); + memory_insert_ok_ovewrite_same_value(); + printf("--------------------------------- \n"); printf("Test: memory_load_data_empty \n"); memory_load_data_empty(); printf("--------------------------------- \n"); From 1b22061fa5619e29f5b819c5e91023babacd6a0a Mon Sep 17 00:00:00 2001 From: Federica Date: Thu, 20 Jul 2023 05:10:17 -0300 Subject: [PATCH 22/59] Add test --- test/memory_tests.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/test/memory_tests.c b/test/memory_tests.c index 22927c1..2ca57d2 100644 --- a/test/memory_tests.c +++ b/test/memory_tests.c @@ -53,6 +53,21 @@ void memory_insert_ok_ovewrite_same_value(void) { printf("OK!\n"); } +void memory_insert_ok(void) { + // Initialize memory + memory mem = memory_new(); + memory_add_segment(&mem); + relocatable ptr = {0, 0}; + maybe_relocatable elem = {.is_felt = true, .value = {.felt = 1}}; + ResultMemory result_insert = memory_insert(&mem, ptr, elem); + assert(!result_insert.is_error); + assert(result_insert.value.none == 0); + ResultMemory result_get = memory_get(&mem, ptr); + assert(!result_get.is_error); + assert(result_get.value.memory_value.value.felt == 1); + printf("OK!\n"); +} + void memory_load_data_one_element(void) { // Initialize memory memory mem = memory_new(); @@ -102,6 +117,9 @@ void memory_tests(void) { printf("Test: memory_insert_ok_ovewrite_same_value \n"); memory_insert_ok_ovewrite_same_value(); printf("--------------------------------- \n"); + printf("Test: memory_insert_ok \n"); + memory_get_err(); + printf("--------------------------------- \n"); printf("Test: memory_load_data_empty \n"); memory_load_data_empty(); printf("--------------------------------- \n"); From c2ee7ae73a25b1523e042ece313575eae1fa87a9 Mon Sep 17 00:00:00 2001 From: Milton Date: Thu, 20 Jul 2023 11:38:17 -0300 Subject: [PATCH 23/59] Fix converion functions --- src/main.c | 3 +-- src/utils.c | 63 +++++++++++++++++++++++++++++++++++++---------------- src/utils.h | 10 ++++++--- 3 files changed, 52 insertions(+), 24 deletions(-) diff --git a/src/main.c b/src/main.c index de2a586..a2d8be0 100644 --- a/src/main.c +++ b/src/main.c @@ -4,7 +4,6 @@ #include int main(__attribute__((unused)) int argc, __attribute__((unused)) char **argv) { - printf("Hello World!\n"); - + printf("hello word"); return 0; } diff --git a/src/utils.c b/src/utils.c index 66e95f5..6df49ac 100644 --- a/src/utils.c +++ b/src/utils.c @@ -20,58 +20,83 @@ uint8_t *u64_to_be_bytes(uint64_t value, uint8_t *buffer_bytes) { uint64_t u64_from_le_bytes(uint8_t *bytes) { uint64_t value = 0; for (int i = 7; i >= 0; i--) { - value |= bytes[i]; - value = value << (8 * i); + value |= bytes[i] << (8 * i); } return value; } -// TODO: needs fix uint64_t u64_from_be_bytes(uint8_t *bytes) { uint64_t value = 0; for (int i = 0; i < 8; i++) { - value |= bytes[i]; - value = value << (8 * i); + value |= bytes[i] << (8 * i); } return value; } // ------------ -// u16 bits +// u32 bits // ------------ -uint8_t *u16_to_le_bytes(uint16_t value, uint8_t *buffer_bytes) { - for (int i = 0; i < 2; i++) { +uint8_t *u32_to_le_bytes(uint32_t value, uint8_t *buffer_bytes) { + for (int i = 0; i < 4; i++) { buffer_bytes[i] = value >> (8 * i) & 0xFF; } return buffer_bytes; } -uint16_t u16_from_le_bytes(uint8_t *bytes) { +uint8_t *u32_to_be_bytes(uint32_t value, uint8_t *buffer_bytes) { + for (int i = 3; i >= 0; i--) { + buffer_bytes[i] = value >> (8 * i) & 0xFF; + } + return buffer_bytes; +} + +uint32_t u32_from_le_bytes(uint8_t *bytes) { uint16_t value = 0; - for (int i = 1; i >= 0; i--) { - value |= bytes[i]; - value = value << (8 * i); + for (int i = 3; i >= 0; i--) { + value |= bytes[i] << (8 * i); + } + return value; +} + +uint32_t u32_from_be_bytes(uint8_t *bytes) { + uint64_t value = 0; + for (int i = 0; i < 4; i++) { + value |= bytes[i] << (8 * i); } return value; } // ------------ -// u32 bits +// u16 bits // ------------ -uint8_t *u32_to_le_bytes(uint32_t value, uint8_t *buffer_bytes) { - for (int i = 0; i < 4; i++) { +uint8_t *u16_to_le_bytes(uint16_t value, uint8_t *buffer_bytes) { + for (int i = 0; i < 2; i++) { buffer_bytes[i] = value >> (8 * i) & 0xFF; } return buffer_bytes; } -uint32_t u32_from_le_bytes(uint8_t *bytes) { +uint8_t *u16_to_be_bytes(uint16_t value, uint8_t *buffer_bytes) { + for (int i = 1; i >= 0; i--) { + buffer_bytes[i] = value >> (8 * i) & 0xFF; + } + return buffer_bytes; +} + +uint16_t u16_from_le_bytes(uint8_t *bytes) { uint16_t value = 0; - for (int i = 3; i >= 0; i--) { - value |= bytes[i]; - value = value << (8 * i); + for (int i = 1; i >= 0; i--) { + value |= bytes[i] << (8 * i); + } + return value; +} + +uint16_t u16_from_be_bytes(uint8_t *bytes) { + uint64_t value = 0; + for (int i = 0; i < 2; i++) { + value |= bytes[i] << (8 * i); } return value; } diff --git a/src/utils.h b/src/utils.h index e26131f..f7a6bed 100644 --- a/src/utils.h +++ b/src/utils.h @@ -9,10 +9,14 @@ uint8_t *u64_to_be_bytes(uint64_t value, uint8_t *buffer_bytes); uint64_t u64_from_le_bytes(uint8_t *bytes); uint64_t u64_from_be_bytes(uint8_t *bytes); -uint8_t *u16_to_le_bytes(uint16_t value, uint8_t *buffer_bytes); -uint16_t u16_from_le_bytes(uint8_t *bytes); - uint8_t *u32_to_le_bytes(uint32_t value, uint8_t *buffer_bytes); +uint8_t *u32_to_be_bytes(uint32_t value, uint8_t *buffer_bytes); uint32_t u32_from_le_bytes(uint8_t *bytes); +uint32_t u32_from_be_bytes(uint8_t *bytes); + +uint8_t *u16_to_le_bytes(uint16_t value, uint8_t *buffer_bytes); +uint8_t *u16_to_be_bytes(uint16_t value, uint8_t *buffer_bytes); +uint16_t u16_from_le_bytes(uint8_t *bytes); +uint64_t u16_from_be_bytes(uint8_t *bytes); #endif From 67956db28acee7b0aa63a8dc9eaf8cb95b5ea4b6 Mon Sep 17 00:00:00 2001 From: Milton Date: Fri, 21 Jul 2023 10:48:31 -0300 Subject: [PATCH 24/59] Fix typos --- src/instruction.h | 1 + src/vm.c | 11 ++++++++++- src/vm.h | 9 ++++++++- test/memory_tests.c | 3 +++ 4 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/instruction.h b/src/instruction.h index 7bd3fa3..519d675 100644 --- a/src/instruction.h +++ b/src/instruction.h @@ -88,6 +88,7 @@ enum VirtualMachineError { InvalidRes, InvalidOpcode, InvalidApUpdate, + None }; union ResultInstructionValue { diff --git a/src/vm.c b/src/vm.c index 485263b..a0b088b 100644 --- a/src/vm.c +++ b/src/vm.c @@ -1,7 +1,16 @@ #include "vm.h" -#include "memory.h" virtual_machine vm_new(void) { virtual_machine vm = {{{0, 0}, {0, 0}, {0, 0}}, memory_new()}; return vm; } + +vm_result run_instruction(Instruction instr) { + + vm_result res = { + .is_ok = true, + .error = None, + }; + + return res; +} diff --git a/src/vm.h b/src/vm.h index b24470c..b185f25 100644 --- a/src/vm.h +++ b/src/vm.h @@ -1,9 +1,16 @@ #ifndef VM_H #define VM_H +#include "instruction.h" #include "memory.h" #include "run_context.h" -typedef struct virtual_machine { + +typedef struct { + enum VirtualMachineError error; + bool is_ok; +} vm_result; + +typedef struct { run_context run_context; memory memory; } virtual_machine; diff --git a/test/memory_tests.c b/test/memory_tests.c index f14f49b..9de399c 100644 --- a/test/memory_tests.c +++ b/test/memory_tests.c @@ -55,6 +55,7 @@ void memory_insert_ok_ovewrite_same_value(void) { maybe_relocatable elem = {.is_felt = true, .value = {.felt = &f}}; ResultMemory result = memory_insert(&mem, ptr, elem); assert(!result.is_error); + maybe_relocatable elem_b = {.is_felt = true, .value = {.felt = &f}}; ResultMemory result_b = memory_insert(&mem, ptr, elem_b); assert(!result_b.is_error); @@ -70,10 +71,12 @@ void memory_insert_ok(void) { one(f); maybe_relocatable elem = {.is_felt = true, .value = {.felt = &f}}; ResultMemory result_insert = memory_insert(&mem, ptr, elem); + assert(!result_insert.is_error); assert(result_insert.value.none == 0); ResultMemory result_get = memory_get(&mem, ptr); assert(!result_get.is_error); + felt_t expected_value; one(expected_value); assert(felt_equal(result_get.value.memory_value.value.felt, &expected_value)); From 2f11a7e0146d8cb136e81d049650f48a48be0635 Mon Sep 17 00:00:00 2001 From: Federica Date: Fri, 21 Jul 2023 10:50:05 -0300 Subject: [PATCH 25/59] Handle memory gaps in memory functions --- src/memory.c | 25 +++++++++++++++++++------ src/memory.h | 12 ++++++++++++ test/memory_tests.c | 20 +++++++++++++++++++- 3 files changed, 50 insertions(+), 7 deletions(-) diff --git a/src/memory.c b/src/memory.c index 80c5e65..5109c49 100644 --- a/src/memory.c +++ b/src/memory.c @@ -20,18 +20,28 @@ ResultMemory memory_get(memory *mem, relocatable ptr) { ResultMemory error = {.is_error = true, .value = {.error = Get}}; return error; } - maybe_relocatable *value = segment->at(segment, ptr.offset); - ResultMemory ok = {.is_error = false, .value = {.memory_value = *value}}; - return ok; + memory_cell *cell = segment->at(segment, ptr.offset); + if (cell->is_some) { + ResultMemory ok = {.is_error = false, .value = {.memory_value = cell->memory_value.value}}; + return ok; + } + ResultMemory error = {.is_error = true, .value = {.error = Get}}; + return error; } ResultMemory memory_insert(memory *mem, relocatable ptr, maybe_relocatable value) { int index = ptr.segment_index; + int offset = ptr.segment_index; if (index >= mem->data->count(mem->data)) { ResultMemory error = {.is_error = true, .value = {.error = Insert}}; return error; } CList *segment = mem->data->at(mem->data, ptr.segment_index); + // Handle gaps + while (segment->count(segment) <= offset) { + memory_cell none = {.is_some = false, .memory_value = {.none = 0}}; + segment->add(segment, &none); + } ResultMemory get_result = memory_get(mem, ptr); // Check for possible ovewrites if (!get_result.is_error) { @@ -43,14 +53,15 @@ ResultMemory memory_insert(memory *mem, relocatable ptr, maybe_relocatable value return error; } } - segment->insert(segment, &value, ptr.offset); + memory_cell new_cell = {.is_some = true, .memory_value = {.value = value}}; + segment->insert(segment, &new_cell, ptr.offset); ResultMemory ok = {.is_error = false, .value = {.none = 0}}; return ok; } relocatable memory_add_segment(memory *memory) { relocatable rel = {memory->num_segments, 0}; - struct CList *segment = CList_init(sizeof(maybe_relocatable)); + struct CList *segment = CList_init(sizeof(memory_cell)); memory->data->add(memory->data, segment); memory->num_segments += 1; return rel; @@ -60,7 +71,9 @@ relocatable memory_load_data(memory *memory, relocatable ptr, CList *data) { int size = data->count(data); CList *segment = memory->data->at(memory->data, ptr.segment_index); for (int i = 0; i < size; i++) { - segment->insert(segment, data->at(data, i), ptr.offset + i); + maybe_relocatable *value = data->at(data, i); + memory_cell new_cell = {.is_some = true, .memory_value = {.value = *value}}; + segment->insert(segment, &new_cell, ptr.offset + i); } ptr.offset += size; return ptr; diff --git a/src/memory.h b/src/memory.h index 3bf9093..287ebdc 100644 --- a/src/memory.h +++ b/src/memory.h @@ -10,6 +10,18 @@ typedef struct memory { CList *data; } memory; +// Inner value + +union memory_value { + maybe_relocatable value; + unsigned int none; +}; + +typedef struct memory_cell { + union memory_value memory_value; + bool is_some; +} memory_cell; + // Error handling enum MemoryError { diff --git a/test/memory_tests.c b/test/memory_tests.c index 2ca57d2..fed1dd5 100644 --- a/test/memory_tests.c +++ b/test/memory_tests.c @@ -68,6 +68,21 @@ void memory_insert_ok(void) { printf("OK!\n"); } +void memory_insert_with_gap(void) { + // Initialize memory + memory mem = memory_new(); + memory_add_segment(&mem); + relocatable ptr = {0, 1}; + maybe_relocatable elem = {.is_felt = true, .value = {.felt = 1}}; + ResultMemory result_insert = memory_insert(&mem, ptr, elem); + assert(!result_insert.is_error); + assert(result_insert.value.none == 0); + ResultMemory result_get = memory_get(&mem, ptr); + assert(!result_get.is_error); + assert(result_get.value.memory_value.value.felt == 1); + printf("OK!\n"); +} + void memory_load_data_one_element(void) { // Initialize memory memory mem = memory_new(); @@ -118,7 +133,10 @@ void memory_tests(void) { memory_insert_ok_ovewrite_same_value(); printf("--------------------------------- \n"); printf("Test: memory_insert_ok \n"); - memory_get_err(); + memory_insert_ok(); + printf("--------------------------------- \n"); + printf("Test: memory_insert_with_gap \n"); + memory_insert_with_gap(); printf("--------------------------------- \n"); printf("Test: memory_load_data_empty \n"); memory_load_data_empty(); From 65cb9016904a9a26535aa618bd7faf5e8b8428e6 Mon Sep 17 00:00:00 2001 From: Federica Date: Fri, 21 Jul 2023 10:55:02 -0300 Subject: [PATCH 26/59] Add more tests --- test/memory_tests.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/test/memory_tests.c b/test/memory_tests.c index fed1dd5..a3b81a6 100644 --- a/test/memory_tests.c +++ b/test/memory_tests.c @@ -118,6 +118,14 @@ void memory_load_data_empty(void) { printf("OK!\n"); } +void memory_add_segment_ok(void) { + // Initialize memory + memory mem = memory_new(); + memory_add_segment(&mem); + assert(mem.data->count(mem.data) == 1); + printf("OK!\n"); +} + void memory_tests(void) { printf("--------------------------------- \n"); printf("Test: memory_get_err \n"); @@ -143,4 +151,7 @@ void memory_tests(void) { printf("--------------------------------- \n"); printf("Test: memory_load_data_one_element \n"); memory_load_data_one_element(); + printf("--------------------------------- \n"); + printf("Test: memory_add_segment_ok \n"); + memory_add_segment_ok(); } From 8093541e476c93fd7bb059afbe4455c42662fd18 Mon Sep 17 00:00:00 2001 From: Federica Date: Fri, 21 Jul 2023 11:00:20 -0300 Subject: [PATCH 27/59] Fix bug --- src/cairo_runner.c | 6 ++++-- test/memory_tests.c | 1 + test/test.c | 1 + 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/cairo_runner.c b/src/cairo_runner.c index 04b04e9..e968b2c 100644 --- a/src/cairo_runner.c +++ b/src/cairo_runner.c @@ -27,8 +27,10 @@ void runner_initialize_state(cairo_runner *runner, unsigned int entrypoint) { relocatable runner_initialize_function_entrypoint(cairo_runner *runner, unsigned int entrypoint, CList *stack, relocatable return_fp) { relocatable end = memory_add_segment(&runner->vm.memory); - stack->add(stack, &return_fp); - stack->add(stack, &end); + maybe_relocatable return_fp_mr = {.is_felt = false, .value = {.relocatable = return_fp}}; + maybe_relocatable end_mr = {.is_felt = false, .value = {.relocatable = end}}; + stack->add(stack, &return_fp_mr); + stack->add(stack, &end_mr); runner->initial_fp.segment_index = runner->execution_base.segment_index; runner->initial_fp.offset = stack->count(stack); runner_initialize_state(runner, entrypoint); diff --git a/test/memory_tests.c b/test/memory_tests.c index a3b81a6..52a50b6 100644 --- a/test/memory_tests.c +++ b/test/memory_tests.c @@ -123,6 +123,7 @@ void memory_add_segment_ok(void) { memory mem = memory_new(); memory_add_segment(&mem); assert(mem.data->count(mem.data) == 1); + assert(mem.num_segments == 1); printf("OK!\n"); } diff --git a/test/test.c b/test/test.c index 8d5874b..44af25b 100644 --- a/test/test.c +++ b/test/test.c @@ -8,5 +8,6 @@ int main(__attribute__((unused)) int argc, __attribute__((unused)) char **argv) { decoding_tests(); memory_tests(); + runner_tests(); return 0; } From d026137f7a1eb6bf2bc019c5ada3f9abff161fd2 Mon Sep 17 00:00:00 2001 From: Federica Date: Fri, 21 Jul 2023 11:07:41 -0300 Subject: [PATCH 28/59] Add tests --- test/memory_tests.c | 6 +++--- test/runner_tests.c | 39 +++++++++++++++++++++++++++++++++++---- 2 files changed, 38 insertions(+), 7 deletions(-) diff --git a/test/memory_tests.c b/test/memory_tests.c index 52a50b6..0d9a437 100644 --- a/test/memory_tests.c +++ b/test/memory_tests.c @@ -123,8 +123,8 @@ void memory_add_segment_ok(void) { memory mem = memory_new(); memory_add_segment(&mem); assert(mem.data->count(mem.data) == 1); - assert(mem.num_segments == 1); - printf("OK!\n"); + assert(mem.num_segments == 1); + printf("OK!\n"); } void memory_tests(void) { @@ -152,7 +152,7 @@ void memory_tests(void) { printf("--------------------------------- \n"); printf("Test: memory_load_data_one_element \n"); memory_load_data_one_element(); - printf("--------------------------------- \n"); + printf("--------------------------------- \n"); printf("Test: memory_add_segment_ok \n"); memory_add_segment_ok(); } diff --git a/test/runner_tests.c b/test/runner_tests.c index 9c1054a..656540c 100644 --- a/test/runner_tests.c +++ b/test/runner_tests.c @@ -7,6 +7,34 @@ #include #include +void initialize_runner_no_builtins_no_proof_mode_non_empty_program(void) { + struct CList *program_data = CList_init(sizeof(maybe_relocatable)); + maybe_relocatable elem = {.is_felt = true, .value = {.felt = 1}}; + program_data->add(program_data, &elem); + struct program program = {0, program_data}; + cairo_runner runner = runner_new(program); + runner_initialize(&runner); + // Check runner data + assert(runner.program_base.segment_index == 0 && runner.program_base.offset == 0); + assert(runner.execution_base.segment_index == 1 && runner.execution_base.offset == 0); + assert(runner.initial_pc.segment_index == 0 && runner.initial_pc.offset == 0); + assert(runner.initial_fp.segment_index == 1 && runner.initial_fp.offset == 2); + assert(runner.final_pc.segment_index == 3 && runner.final_pc.offset == 0); + // Check vm data + run_context run_context = runner.vm.run_context; + assert(run_context.pc.segment_index == 0 && run_context.pc.offset == 0); + assert(run_context.ap.segment_index == 1 && run_context.ap.offset == 2); + assert(run_context.fp.segment_index == 1 && run_context.fp.offset == 2); + // Check memory + memory memory = runner.vm.memory; + assert(memory.num_segments == 4); + relocatable ptr = {0, 0}; + ResultMemory result = memory_get(&memory, ptr); + assert(!result.is_error); + assert(result.value.memory_value.value.felt == 1); + printf("OK!\n"); +} + void initialize_runner_no_builtins_no_proof_mode_empty_program(void) { struct CList *program_data = CList_init(sizeof(maybe_relocatable)); struct program program = {0, program_data}; @@ -26,14 +54,17 @@ void initialize_runner_no_builtins_no_proof_mode_empty_program(void) { // Check memory memory memory = runner.vm.memory; assert(memory.num_segments == 4); - assert(memory.data->count(memory.data) == 4); - // check individual segments - struct CList *segment_0 = memory.data->at(memory.data, 0); - assert(segment_0->count(segment_0) == 0); + relocatable ptr = {0, 0}; + ResultMemory result = memory_get(&memory, ptr); + assert(result.is_error); + printf("OK!\n"); } void runner_tests(void) { printf("--------------------------------- \n"); printf("Test: initialize_runner_no_builtins_no_proof_mode_empty_program \n"); initialize_runner_no_builtins_no_proof_mode_empty_program(); + printf("--------------------------------- \n"); + printf("Test: initialize_runner_no_builtins_no_proof_mode_non_empty_program \n"); + initialize_runner_no_builtins_no_proof_mode_empty_program(); } From d1b7492419c5c005fdac554ddfa135a840eac932 Mon Sep 17 00:00:00 2001 From: Federica Date: Mon, 24 Jul 2023 11:10:39 -0300 Subject: [PATCH 29/59] Use felt_t in maybe_relocatable + adapt tests --- src/relocatable.c | 8 +++++++- src/relocatable.h | 6 ++++-- src/utils.c | 4 ++++ src/utils.h | 4 ++++ test/felt_test.c | 1 + test/memory_tests.c | 33 +++++++++++++++++++++++---------- test/runner_tests.c | 7 +++++-- test/test.c | 2 +- 8 files changed, 49 insertions(+), 16 deletions(-) diff --git a/src/relocatable.c b/src/relocatable.c index b7121fb..a3ce412 100644 --- a/src/relocatable.c +++ b/src/relocatable.c @@ -1,8 +1,9 @@ #include "relocatable.h" +#include "utils.h" bool maybe_relocatable_equal(maybe_relocatable a, maybe_relocatable b) { if (a.is_felt && b.is_felt) { - return a.value.felt == b.value.felt; + return felt_equal(a.value.felt, b.value.felt); } else if (!a.is_felt && !b.is_felt) { return a.value.relocatable.segment_index == b.value.relocatable.segment_index && a.value.relocatable.offset == b.value.relocatable.offset; @@ -10,3 +11,8 @@ bool maybe_relocatable_equal(maybe_relocatable a, maybe_relocatable b) { return false; } } + +maybe_relocatable maybe_relocatable_from_felt_unwrapped(unsigned long long *felt) { + maybe_relocatable elem = {.is_felt = true, .value = {.felt = {felt[0], felt[1], felt[2], felt[3]}}}; + return elem; +} diff --git a/src/relocatable.h b/src/relocatable.h index 21e931a..f02e356 100644 --- a/src/relocatable.h +++ b/src/relocatable.h @@ -1,6 +1,6 @@ #ifndef RELOCATABLE_H #define RELOCATABLE_H - +#include "../lambdaworks/lib/lambdaworks.h" #include typedef struct relocatable { @@ -10,7 +10,7 @@ typedef struct relocatable { union maybe_relocatable_value { struct relocatable relocatable; - unsigned int felt; // TODO use a felt type + felt_t felt; }; typedef struct maybe_relocatable { @@ -20,4 +20,6 @@ typedef struct maybe_relocatable { bool maybe_relocatable_equal(maybe_relocatable a, maybe_relocatable b); +maybe_relocatable maybe_relocatable_from_felt_unwrapped(unsigned long long *felt); + #endif diff --git a/src/utils.c b/src/utils.c index 66e95f5..c48249d 100644 --- a/src/utils.c +++ b/src/utils.c @@ -1,4 +1,8 @@ #include "utils.h" +#include + +bool felt_equal(felt_t a, felt_t b) { return (a[0] == b[0] && a[1] == b[1] && a[2] == b[2] && a[3] == b[3]); } + // ------------ // u64 bits // ------------ diff --git a/src/utils.h b/src/utils.h index e26131f..88fa4ed 100644 --- a/src/utils.h +++ b/src/utils.h @@ -1,8 +1,12 @@ #ifndef UTILS_H #define UTILS_H +#include "../lambdaworks/lib/lambdaworks.h" #include "stdint.h" #include "stdio.h" +#include + +bool felt_equal(felt_t a, felt_t b); uint8_t *u64_to_le_bytes(uint64_t value, uint8_t *buffer_bytes); uint8_t *u64_to_be_bytes(uint64_t value, uint8_t *buffer_bytes); diff --git a/test/felt_test.c b/test/felt_test.c index 0be1879..e6ffc22 100644 --- a/test/felt_test.c +++ b/test/felt_test.c @@ -1,4 +1,5 @@ #include "felt_test.h" +#include void felt_sub(void) { felt_t f_one; diff --git a/test/memory_tests.c b/test/memory_tests.c index 0d9a437..0224d7c 100644 --- a/test/memory_tests.c +++ b/test/memory_tests.c @@ -1,5 +1,6 @@ #include "memory_tests.h" #include "relocatable.h" +#include "utils.h" #include #include @@ -17,7 +18,7 @@ void memory_insert_err_unallocated_segement(void) { // Initialize memory memory mem = memory_new(); relocatable ptr = {0, 0}; - maybe_relocatable elem = {.is_felt = true, .value = {.felt = 1}}; + maybe_relocatable elem = {.is_felt = true, .value = {.felt = {1}}}; ResultMemory result = memory_insert(&mem, ptr, elem); assert(result.is_error); assert(result.value.error == Insert); @@ -29,10 +30,14 @@ void memory_insert_err_ovewrite_attempt(void) { memory mem = memory_new(); memory_add_segment(&mem); relocatable ptr = {0, 0}; - maybe_relocatable elem = {.is_felt = true, .value = {.felt = 1}}; + felt_t felt_one; + one(felt_one); + maybe_relocatable elem = maybe_relocatable_from_felt_unwrapped(felt_one); ResultMemory result = memory_insert(&mem, ptr, elem); assert(!result.is_error); - maybe_relocatable elem_b = {.is_felt = true, .value = {.felt = 2}}; + felt_t felt_two; + from(felt_two, 2); + maybe_relocatable elem_b = maybe_relocatable_from_felt_unwrapped(felt_two); ResultMemory result_b = memory_insert(&mem, ptr, elem_b); assert(result_b.is_error); assert(result_b.value.error == Insert); @@ -44,10 +49,12 @@ void memory_insert_ok_ovewrite_same_value(void) { memory mem = memory_new(); memory_add_segment(&mem); relocatable ptr = {0, 0}; - maybe_relocatable elem = {.is_felt = true, .value = {.felt = 1}}; + felt_t felt_one; + one(felt_one); + maybe_relocatable elem = maybe_relocatable_from_felt_unwrapped(felt_one); ResultMemory result = memory_insert(&mem, ptr, elem); assert(!result.is_error); - maybe_relocatable elem_b = {.is_felt = true, .value = {.felt = 1}}; + maybe_relocatable elem_b = maybe_relocatable_from_felt_unwrapped(felt_one); ResultMemory result_b = memory_insert(&mem, ptr, elem_b); assert(!result_b.is_error); printf("OK!\n"); @@ -58,13 +65,15 @@ void memory_insert_ok(void) { memory mem = memory_new(); memory_add_segment(&mem); relocatable ptr = {0, 0}; - maybe_relocatable elem = {.is_felt = true, .value = {.felt = 1}}; + felt_t felt_one; + one(felt_one); + maybe_relocatable elem = maybe_relocatable_from_felt_unwrapped(felt_one); ResultMemory result_insert = memory_insert(&mem, ptr, elem); assert(!result_insert.is_error); assert(result_insert.value.none == 0); ResultMemory result_get = memory_get(&mem, ptr); assert(!result_get.is_error); - assert(result_get.value.memory_value.value.felt == 1); + assert(felt_equal(result_get.value.memory_value.value.felt, felt_one)); printf("OK!\n"); } @@ -73,13 +82,15 @@ void memory_insert_with_gap(void) { memory mem = memory_new(); memory_add_segment(&mem); relocatable ptr = {0, 1}; - maybe_relocatable elem = {.is_felt = true, .value = {.felt = 1}}; + felt_t felt_one; + one(felt_one); + maybe_relocatable elem = maybe_relocatable_from_felt_unwrapped(felt_one); ResultMemory result_insert = memory_insert(&mem, ptr, elem); assert(!result_insert.is_error); assert(result_insert.value.none == 0); ResultMemory result_get = memory_get(&mem, ptr); assert(!result_get.is_error); - assert(result_get.value.memory_value.value.felt == 1); + assert(felt_equal(result_get.value.memory_value.value.felt, felt_one)); printf("OK!\n"); } @@ -89,7 +100,9 @@ void memory_load_data_one_element(void) { memory_add_segment(&mem); // Initialize data to load struct CList *data = CList_init(sizeof(maybe_relocatable)); - maybe_relocatable elem = {.is_felt = true, .value = {.felt = 1}}; + felt_t felt_one; + one(felt_one); + maybe_relocatable elem = maybe_relocatable_from_felt_unwrapped(felt_one); data->add(data, &elem); relocatable ptr = {0, 0}; // Load data diff --git a/test/runner_tests.c b/test/runner_tests.c index 656540c..3b08e59 100644 --- a/test/runner_tests.c +++ b/test/runner_tests.c @@ -3,13 +3,16 @@ #include "memory.h" #include "program.h" #include "run_context.h" +#include "utils.h" #include "vm.h" #include #include void initialize_runner_no_builtins_no_proof_mode_non_empty_program(void) { struct CList *program_data = CList_init(sizeof(maybe_relocatable)); - maybe_relocatable elem = {.is_felt = true, .value = {.felt = 1}}; + felt_t felt_one; + one(felt_one); + maybe_relocatable elem = maybe_relocatable_from_felt_unwrapped(felt_one); program_data->add(program_data, &elem); struct program program = {0, program_data}; cairo_runner runner = runner_new(program); @@ -31,7 +34,7 @@ void initialize_runner_no_builtins_no_proof_mode_non_empty_program(void) { relocatable ptr = {0, 0}; ResultMemory result = memory_get(&memory, ptr); assert(!result.is_error); - assert(result.value.memory_value.value.felt == 1); + assert(felt_equal(result.value.memory_value.value.felt, felt_one)); printf("OK!\n"); } diff --git a/test/test.c b/test/test.c index efa085e..0488bbd 100644 --- a/test/test.c +++ b/test/test.c @@ -1,7 +1,7 @@ #include "decoder_test.h" +#include "felt_test.h" #include "memory_tests.h" #include "runner_tests.h" -#include "felt_test.h" #include #include From 27ad5c5cf00f95c97ff231b1f52f15c44595090c Mon Sep 17 00:00:00 2001 From: Federica Date: Mon, 24 Jul 2023 11:15:41 -0300 Subject: [PATCH 30/59] Rename function & change parameter type --- src/relocatable.c | 2 +- src/relocatable.h | 2 +- test/memory_tests.c | 14 +++++++------- test/runner_tests.c | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/relocatable.c b/src/relocatable.c index a3ce412..1a84945 100644 --- a/src/relocatable.c +++ b/src/relocatable.c @@ -12,7 +12,7 @@ bool maybe_relocatable_equal(maybe_relocatable a, maybe_relocatable b) { } } -maybe_relocatable maybe_relocatable_from_felt_unwrapped(unsigned long long *felt) { +maybe_relocatable maybe_relocatable_from_felt_limbs(limb_t *felt) { maybe_relocatable elem = {.is_felt = true, .value = {.felt = {felt[0], felt[1], felt[2], felt[3]}}}; return elem; } diff --git a/src/relocatable.h b/src/relocatable.h index f02e356..88562e7 100644 --- a/src/relocatable.h +++ b/src/relocatable.h @@ -20,6 +20,6 @@ typedef struct maybe_relocatable { bool maybe_relocatable_equal(maybe_relocatable a, maybe_relocatable b); -maybe_relocatable maybe_relocatable_from_felt_unwrapped(unsigned long long *felt); +maybe_relocatable maybe_relocatable_from_felt_limbs(limb_t *felt); #endif diff --git a/test/memory_tests.c b/test/memory_tests.c index 0224d7c..a7bd20c 100644 --- a/test/memory_tests.c +++ b/test/memory_tests.c @@ -32,12 +32,12 @@ void memory_insert_err_ovewrite_attempt(void) { relocatable ptr = {0, 0}; felt_t felt_one; one(felt_one); - maybe_relocatable elem = maybe_relocatable_from_felt_unwrapped(felt_one); + maybe_relocatable elem = maybe_relocatable_from_felt_limbs(felt_one); ResultMemory result = memory_insert(&mem, ptr, elem); assert(!result.is_error); felt_t felt_two; from(felt_two, 2); - maybe_relocatable elem_b = maybe_relocatable_from_felt_unwrapped(felt_two); + maybe_relocatable elem_b = maybe_relocatable_from_felt_limbs(felt_two); ResultMemory result_b = memory_insert(&mem, ptr, elem_b); assert(result_b.is_error); assert(result_b.value.error == Insert); @@ -51,10 +51,10 @@ void memory_insert_ok_ovewrite_same_value(void) { relocatable ptr = {0, 0}; felt_t felt_one; one(felt_one); - maybe_relocatable elem = maybe_relocatable_from_felt_unwrapped(felt_one); + maybe_relocatable elem = maybe_relocatable_from_felt_limbs(felt_one); ResultMemory result = memory_insert(&mem, ptr, elem); assert(!result.is_error); - maybe_relocatable elem_b = maybe_relocatable_from_felt_unwrapped(felt_one); + maybe_relocatable elem_b = maybe_relocatable_from_felt_limbs(felt_one); ResultMemory result_b = memory_insert(&mem, ptr, elem_b); assert(!result_b.is_error); printf("OK!\n"); @@ -67,7 +67,7 @@ void memory_insert_ok(void) { relocatable ptr = {0, 0}; felt_t felt_one; one(felt_one); - maybe_relocatable elem = maybe_relocatable_from_felt_unwrapped(felt_one); + maybe_relocatable elem = maybe_relocatable_from_felt_limbs(felt_one); ResultMemory result_insert = memory_insert(&mem, ptr, elem); assert(!result_insert.is_error); assert(result_insert.value.none == 0); @@ -84,7 +84,7 @@ void memory_insert_with_gap(void) { relocatable ptr = {0, 1}; felt_t felt_one; one(felt_one); - maybe_relocatable elem = maybe_relocatable_from_felt_unwrapped(felt_one); + maybe_relocatable elem = maybe_relocatable_from_felt_limbs(felt_one); ResultMemory result_insert = memory_insert(&mem, ptr, elem); assert(!result_insert.is_error); assert(result_insert.value.none == 0); @@ -102,7 +102,7 @@ void memory_load_data_one_element(void) { struct CList *data = CList_init(sizeof(maybe_relocatable)); felt_t felt_one; one(felt_one); - maybe_relocatable elem = maybe_relocatable_from_felt_unwrapped(felt_one); + maybe_relocatable elem = maybe_relocatable_from_felt_limbs(felt_one); data->add(data, &elem); relocatable ptr = {0, 0}; // Load data diff --git a/test/runner_tests.c b/test/runner_tests.c index 3b08e59..1b51c30 100644 --- a/test/runner_tests.c +++ b/test/runner_tests.c @@ -12,7 +12,7 @@ void initialize_runner_no_builtins_no_proof_mode_non_empty_program(void) { struct CList *program_data = CList_init(sizeof(maybe_relocatable)); felt_t felt_one; one(felt_one); - maybe_relocatable elem = maybe_relocatable_from_felt_unwrapped(felt_one); + maybe_relocatable elem = maybe_relocatable_from_felt_limbs(felt_one); program_data->add(program_data, &elem); struct program program = {0, program_data}; cairo_runner runner = runner_new(program); From c3da19786d7d99b3fc98ecaa2c1f0dbdfe932464 Mon Sep 17 00:00:00 2001 From: Federica Date: Mon, 24 Jul 2023 11:19:14 -0300 Subject: [PATCH 31/59] Remove unused import --- src/utils.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/utils.c b/src/utils.c index c48249d..bb737ff 100644 --- a/src/utils.c +++ b/src/utils.c @@ -1,5 +1,4 @@ #include "utils.h" -#include bool felt_equal(felt_t a, felt_t b) { return (a[0] == b[0] && a[1] == b[1] && a[2] == b[2] && a[3] == b[3]); } From f147768fc6ba089649a9d4a61e265a8b55e78673 Mon Sep 17 00:00:00 2001 From: Federica Date: Mon, 24 Jul 2023 11:19:52 -0300 Subject: [PATCH 32/59] Remove unused import --- test/felt_test.c | 1 - 1 file changed, 1 deletion(-) diff --git a/test/felt_test.c b/test/felt_test.c index e6ffc22..0be1879 100644 --- a/test/felt_test.c +++ b/test/felt_test.c @@ -1,5 +1,4 @@ #include "felt_test.h" -#include void felt_sub(void) { felt_t f_one; From 17261415d00735ed9657f23d59a39349075811d4 Mon Sep 17 00:00:00 2001 From: Federica Date: Mon, 24 Jul 2023 11:29:41 -0300 Subject: [PATCH 33/59] Add memory_free function --- src/memory.c | 9 +++++++++ src/memory.h | 2 ++ 2 files changed, 11 insertions(+) diff --git a/src/memory.c b/src/memory.c index 5109c49..b7e7b20 100644 --- a/src/memory.c +++ b/src/memory.c @@ -78,3 +78,12 @@ relocatable memory_load_data(memory *memory, relocatable ptr, CList *data) { ptr.offset += size; return ptr; } + +void memory_free(memory *mem) { + int num_segments = mem->num_segments; + for (int i = 0; i < num_segments; i++) { + CList *segment = mem->data->at(mem->data, i); + segment->free(segment); + } + mem->data->free(mem->data); +} diff --git a/src/memory.h b/src/memory.h index 287ebdc..3dec78d 100644 --- a/src/memory.h +++ b/src/memory.h @@ -52,4 +52,6 @@ relocatable memory_add_segment(memory *memory); relocatable memory_load_data(memory *memory, relocatable ptr, CList *data); +void memory_free(memory *mem); + #endif From e778bb9ee22093bc7cad13c78e0475dcc4da9ef2 Mon Sep 17 00:00:00 2001 From: Federica Date: Mon, 24 Jul 2023 11:34:57 -0300 Subject: [PATCH 34/59] Free memory in memory_tests --- src/memory.c | 10 +++++----- test/memory_tests.c | 9 +++++++++ 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/memory.c b/src/memory.c index b7e7b20..ea881e7 100644 --- a/src/memory.c +++ b/src/memory.c @@ -80,10 +80,10 @@ relocatable memory_load_data(memory *memory, relocatable ptr, CList *data) { } void memory_free(memory *mem) { - int num_segments = mem->num_segments; - for (int i = 0; i < num_segments; i++) { - CList *segment = mem->data->at(mem->data, i); - segment->free(segment); - } + // int num_segments = mem->num_segments; + // for (int i = 0; i < num_segments; i++) { + // CList *segment = mem->data->at(mem->data, i); + // segment->free(segment); + // } mem->data->free(mem->data); } diff --git a/test/memory_tests.c b/test/memory_tests.c index a7bd20c..275fe59 100644 --- a/test/memory_tests.c +++ b/test/memory_tests.c @@ -11,6 +11,7 @@ void memory_get_err(void) { ResultMemory result = memory_get(&mem, ptr); assert(result.is_error); assert(result.value.error == Get); + memory_free(&mem); printf("OK!\n"); } @@ -22,6 +23,7 @@ void memory_insert_err_unallocated_segement(void) { ResultMemory result = memory_insert(&mem, ptr, elem); assert(result.is_error); assert(result.value.error == Insert); + memory_free(&mem); printf("OK!\n"); } @@ -41,6 +43,7 @@ void memory_insert_err_ovewrite_attempt(void) { ResultMemory result_b = memory_insert(&mem, ptr, elem_b); assert(result_b.is_error); assert(result_b.value.error == Insert); + memory_free(&mem); printf("OK!\n"); } @@ -57,6 +60,7 @@ void memory_insert_ok_ovewrite_same_value(void) { maybe_relocatable elem_b = maybe_relocatable_from_felt_limbs(felt_one); ResultMemory result_b = memory_insert(&mem, ptr, elem_b); assert(!result_b.is_error); + memory_free(&mem); printf("OK!\n"); } @@ -74,6 +78,7 @@ void memory_insert_ok(void) { ResultMemory result_get = memory_get(&mem, ptr); assert(!result_get.is_error); assert(felt_equal(result_get.value.memory_value.value.felt, felt_one)); + memory_free(&mem); printf("OK!\n"); } @@ -91,6 +96,7 @@ void memory_insert_with_gap(void) { ResultMemory result_get = memory_get(&mem, ptr); assert(!result_get.is_error); assert(felt_equal(result_get.value.memory_value.value.felt, felt_one)); + memory_free(&mem); printf("OK!\n"); } @@ -112,6 +118,7 @@ void memory_load_data_one_element(void) { ResultMemory result = memory_get(&mem, ptr); assert(!result.is_error); assert(maybe_relocatable_equal(result.value.memory_value, elem)); + memory_free(&mem); printf("OK!\n"); } @@ -128,6 +135,7 @@ void memory_load_data_empty(void) { // Check memory ResultMemory result = memory_get(&mem, ptr); assert(result.is_error); + memory_free(&mem); printf("OK!\n"); } @@ -137,6 +145,7 @@ void memory_add_segment_ok(void) { memory_add_segment(&mem); assert(mem.data->count(mem.data) == 1); assert(mem.num_segments == 1); + memory_free(&mem); printf("OK!\n"); } From 31ffde54b5b5b218b40f69e2ac5c06bcb2e63235 Mon Sep 17 00:00:00 2001 From: Federica Date: Mon, 24 Jul 2023 11:36:17 -0300 Subject: [PATCH 35/59] fmt --- test/memory_tests.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/test/memory_tests.c b/test/memory_tests.c index 275fe59..390f8ac 100644 --- a/test/memory_tests.c +++ b/test/memory_tests.c @@ -11,7 +11,7 @@ void memory_get_err(void) { ResultMemory result = memory_get(&mem, ptr); assert(result.is_error); assert(result.value.error == Get); - memory_free(&mem); + memory_free(&mem); printf("OK!\n"); } @@ -23,7 +23,7 @@ void memory_insert_err_unallocated_segement(void) { ResultMemory result = memory_insert(&mem, ptr, elem); assert(result.is_error); assert(result.value.error == Insert); - memory_free(&mem); + memory_free(&mem); printf("OK!\n"); } @@ -43,7 +43,7 @@ void memory_insert_err_ovewrite_attempt(void) { ResultMemory result_b = memory_insert(&mem, ptr, elem_b); assert(result_b.is_error); assert(result_b.value.error == Insert); - memory_free(&mem); + memory_free(&mem); printf("OK!\n"); } @@ -60,7 +60,7 @@ void memory_insert_ok_ovewrite_same_value(void) { maybe_relocatable elem_b = maybe_relocatable_from_felt_limbs(felt_one); ResultMemory result_b = memory_insert(&mem, ptr, elem_b); assert(!result_b.is_error); - memory_free(&mem); + memory_free(&mem); printf("OK!\n"); } @@ -78,7 +78,7 @@ void memory_insert_ok(void) { ResultMemory result_get = memory_get(&mem, ptr); assert(!result_get.is_error); assert(felt_equal(result_get.value.memory_value.value.felt, felt_one)); - memory_free(&mem); + memory_free(&mem); printf("OK!\n"); } @@ -96,7 +96,7 @@ void memory_insert_with_gap(void) { ResultMemory result_get = memory_get(&mem, ptr); assert(!result_get.is_error); assert(felt_equal(result_get.value.memory_value.value.felt, felt_one)); - memory_free(&mem); + memory_free(&mem); printf("OK!\n"); } @@ -118,7 +118,7 @@ void memory_load_data_one_element(void) { ResultMemory result = memory_get(&mem, ptr); assert(!result.is_error); assert(maybe_relocatable_equal(result.value.memory_value, elem)); - memory_free(&mem); + memory_free(&mem); printf("OK!\n"); } @@ -135,7 +135,7 @@ void memory_load_data_empty(void) { // Check memory ResultMemory result = memory_get(&mem, ptr); assert(result.is_error); - memory_free(&mem); + memory_free(&mem); printf("OK!\n"); } @@ -145,7 +145,7 @@ void memory_add_segment_ok(void) { memory_add_segment(&mem); assert(mem.data->count(mem.data) == 1); assert(mem.num_segments == 1); - memory_free(&mem); + memory_free(&mem); printf("OK!\n"); } From 8d16b3fbbc5bcfdcf18eecfc9f2dfafe5645e926 Mon Sep 17 00:00:00 2001 From: Federica Date: Mon, 24 Jul 2023 11:40:43 -0300 Subject: [PATCH 36/59] Use clear in stead of free --- src/memory.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/memory.c b/src/memory.c index ea881e7..13566c2 100644 --- a/src/memory.c +++ b/src/memory.c @@ -80,10 +80,10 @@ relocatable memory_load_data(memory *memory, relocatable ptr, CList *data) { } void memory_free(memory *mem) { - // int num_segments = mem->num_segments; - // for (int i = 0; i < num_segments; i++) { - // CList *segment = mem->data->at(mem->data, i); - // segment->free(segment); - // } - mem->data->free(mem->data); + int num_segments = mem->num_segments; + for (int i = 0; i < num_segments; i++) { + CList *segment = mem->data->at(mem->data, i); + segment->clear(segment); + } + mem->data->clear(mem->data); } From 2dc7b1e72c480366ac15e0672a1d06a340d1c3b0 Mon Sep 17 00:00:00 2001 From: Federica Date: Mon, 24 Jul 2023 11:43:37 -0300 Subject: [PATCH 37/59] Free runner --- src/cairo_runner.c | 2 ++ src/cairo_runner.h | 2 ++ test/runner_tests.c | 2 ++ 3 files changed, 6 insertions(+) diff --git a/src/cairo_runner.c b/src/cairo_runner.c index e968b2c..e928784 100644 --- a/src/cairo_runner.c +++ b/src/cairo_runner.c @@ -9,6 +9,8 @@ cairo_runner runner_new(struct program program) { return runner; } +void runner_free(cairo_runner *runner) { memory_free(&runner->vm.memory); } + void runner_initialize_segments(cairo_runner *runner) { // Program Segment runner->program_base = memory_add_segment(&runner->vm.memory); diff --git a/src/cairo_runner.h b/src/cairo_runner.h index 3daf93b..9fe8a2d 100644 --- a/src/cairo_runner.h +++ b/src/cairo_runner.h @@ -19,6 +19,8 @@ typedef struct cairo_runner { cairo_runner runner_new(struct program program); +void runner_free(cairo_runner *runner); + relocatable runner_initialize(cairo_runner *runner); #endif diff --git a/test/runner_tests.c b/test/runner_tests.c index 1b51c30..214666a 100644 --- a/test/runner_tests.c +++ b/test/runner_tests.c @@ -35,6 +35,7 @@ void initialize_runner_no_builtins_no_proof_mode_non_empty_program(void) { ResultMemory result = memory_get(&memory, ptr); assert(!result.is_error); assert(felt_equal(result.value.memory_value.value.felt, felt_one)); + runner_free(&runner); printf("OK!\n"); } @@ -60,6 +61,7 @@ void initialize_runner_no_builtins_no_proof_mode_empty_program(void) { relocatable ptr = {0, 0}; ResultMemory result = memory_get(&memory, ptr); assert(result.is_error); + runner_free(&runner); printf("OK!\n"); } From b9cbaf57dfca99edf5359ebe009aaa13f746fbf3 Mon Sep 17 00:00:00 2001 From: Federica Date: Mon, 24 Jul 2023 11:56:49 -0300 Subject: [PATCH 38/59] Add function comments --- src/cairo_runner.c | 9 +++++++++ src/memory.h | 10 ++++++++++ src/vm.h | 1 + 3 files changed, 20 insertions(+) diff --git a/src/cairo_runner.c b/src/cairo_runner.c index e928784..705a6bc 100644 --- a/src/cairo_runner.c +++ b/src/cairo_runner.c @@ -3,14 +3,17 @@ #include "relocatable.h" #include "vm.h" +// Creates a new, empty cairo_runner cairo_runner runner_new(struct program program) { virtual_machine vm = vm_new(); cairo_runner runner = {program, vm, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}; return runner; } +// Frees resources used by the cairo_runner struct void runner_free(cairo_runner *runner) { memory_free(&runner->vm.memory); } +// Creates program, execution and builtin segments void runner_initialize_segments(cairo_runner *runner) { // Program Segment runner->program_base = memory_add_segment(&runner->vm.memory); @@ -19,6 +22,7 @@ void runner_initialize_segments(cairo_runner *runner) { // Initialize builtin segments } +// Initializes the program segment & initial pc void runner_initialize_state(cairo_runner *runner, unsigned int entrypoint) { runner->initial_pc = runner->program_base; runner->initial_pc.offset += entrypoint; @@ -26,6 +30,8 @@ void runner_initialize_state(cairo_runner *runner, unsigned int entrypoint) { // Mark data segment as accessed } +// Initializes memory, initial register values & returns the end pointer (final pc) to run from a given pc offset +// (entrypoint) relocatable runner_initialize_function_entrypoint(cairo_runner *runner, unsigned int entrypoint, CList *stack, relocatable return_fp) { relocatable end = memory_add_segment(&runner->vm.memory); @@ -40,6 +46,7 @@ relocatable runner_initialize_function_entrypoint(cairo_runner *runner, unsigned return end; } +// Initializes memory, initial register values & returns the end pointer (final pc) to run from the main entrypoint relocatable runner_initialize_main_entrypoint(cairo_runner *runner) { CList *stack = CList_init(sizeof(maybe_relocatable)); // Handle builtin initial stack @@ -48,6 +55,7 @@ relocatable runner_initialize_main_entrypoint(cairo_runner *runner) { return runner_initialize_function_entrypoint(runner, runner->program.main, stack, return_fp); } +// Initializes the vm's run_context, adds builtin validation rules & validates memory void runner_initialize_vm(cairo_runner *runner) { runner->vm.run_context.ap = runner->initial_fp; runner->vm.run_context.fp = runner->initial_fp; @@ -56,6 +64,7 @@ void runner_initialize_vm(cairo_runner *runner) { // Apply validation rules to memory } +// Performs the intialization step, leaving the runner ready to run a loaded cairo program from a main entrypoint relocatable runner_initialize(cairo_runner *runner) { // runner_initialize_builtins runner_initialize_segments(runner); diff --git a/src/memory.h b/src/memory.h index 3dec78d..a9b04d6 100644 --- a/src/memory.h +++ b/src/memory.h @@ -4,7 +4,9 @@ #include "clist.h" #include "relocatable.h" #include + // Contains behaviour of memory + memory segment manager +// Memory is inmutable typedef struct memory { unsigned int num_segments; CList *data; @@ -42,16 +44,24 @@ typedef struct ResultMemory { union ResultMemoryValue value; } ResultMemory; +// Functions + +// Creates a new empty memory memory memory_new(void); +// Fetches a value from memory indicated by ptr ResultMemory memory_get(memory *mem, relocatable ptr); +// Inserts value into memory at address ptr ResultMemory memory_insert(memory *mem, relocatable ptr, maybe_relocatable value); +// Adds a memory segment relocatable memory_add_segment(memory *memory); +// Inserts the elements in data sequentially from address ptr and returns the next address after the data relocatable memory_load_data(memory *memory, relocatable ptr, CList *data); +// Frees resources used by the memory struct void memory_free(memory *mem); #endif diff --git a/src/vm.h b/src/vm.h index b24470c..d7e6c70 100644 --- a/src/vm.h +++ b/src/vm.h @@ -8,6 +8,7 @@ typedef struct virtual_machine { memory memory; } virtual_machine; +// Creates a new, empty virtual_machine virtual_machine vm_new(void); #endif From d3c71655b34e6551ec18b086bd85f17a155324f1 Mon Sep 17 00:00:00 2001 From: Federica Date: Mon, 24 Jul 2023 12:17:05 -0300 Subject: [PATCH 39/59] Add missing execution segment data loading --- src/cairo_runner.c | 9 ++++++--- test/runner_tests.c | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/src/cairo_runner.c b/src/cairo_runner.c index 705a6bc..8964dce 100644 --- a/src/cairo_runner.c +++ b/src/cairo_runner.c @@ -23,10 +23,11 @@ void runner_initialize_segments(cairo_runner *runner) { } // Initializes the program segment & initial pc -void runner_initialize_state(cairo_runner *runner, unsigned int entrypoint) { +void runner_initialize_state(cairo_runner *runner, unsigned int entrypoint, CList *stack) { runner->initial_pc = runner->program_base; runner->initial_pc.offset += entrypoint; memory_load_data(&runner->vm.memory, runner->program_base, runner->program.data); + memory_load_data(&runner->vm.memory, runner->execution_base, stack); // Mark data segment as accessed } @@ -41,7 +42,7 @@ relocatable runner_initialize_function_entrypoint(cairo_runner *runner, unsigned stack->add(stack, &end_mr); runner->initial_fp.segment_index = runner->execution_base.segment_index; runner->initial_fp.offset = stack->count(stack); - runner_initialize_state(runner, entrypoint); + runner_initialize_state(runner, entrypoint, stack); runner->final_pc = end; return end; } @@ -52,7 +53,9 @@ relocatable runner_initialize_main_entrypoint(cairo_runner *runner) { // Handle builtin initial stack // Handle proof-mode specific behaviour relocatable return_fp = memory_add_segment(&runner->vm.memory); - return runner_initialize_function_entrypoint(runner, runner->program.main, stack, return_fp); + relocatable end = runner_initialize_function_entrypoint(runner, runner->program.main, stack, return_fp); + stack->free(stack); + return end; } // Initializes the vm's run_context, adds builtin validation rules & validates memory diff --git a/test/runner_tests.c b/test/runner_tests.c index 214666a..3a26b8b 100644 --- a/test/runner_tests.c +++ b/test/runner_tests.c @@ -17,24 +17,41 @@ void initialize_runner_no_builtins_no_proof_mode_non_empty_program(void) { struct program program = {0, program_data}; cairo_runner runner = runner_new(program); runner_initialize(&runner); + // Check runner data assert(runner.program_base.segment_index == 0 && runner.program_base.offset == 0); assert(runner.execution_base.segment_index == 1 && runner.execution_base.offset == 0); assert(runner.initial_pc.segment_index == 0 && runner.initial_pc.offset == 0); assert(runner.initial_fp.segment_index == 1 && runner.initial_fp.offset == 2); assert(runner.final_pc.segment_index == 3 && runner.final_pc.offset == 0); + // Check vm data run_context run_context = runner.vm.run_context; assert(run_context.pc.segment_index == 0 && run_context.pc.offset == 0); assert(run_context.ap.segment_index == 1 && run_context.ap.offset == 2); assert(run_context.fp.segment_index == 1 && run_context.fp.offset == 2); + // Check memory memory memory = runner.vm.memory; assert(memory.num_segments == 4); + // program segment relocatable ptr = {0, 0}; ResultMemory result = memory_get(&memory, ptr); assert(!result.is_error); assert(felt_equal(result.value.memory_value.value.felt, felt_one)); + // execution segment + relocatable ptr_b = {1, 0}; + ResultMemory result_b = memory_get(&memory, ptr_b); + assert(!result_b.is_error); + relocatable value_b = result_b.value.memory_value.value.relocatable; + assert(value_b.segment_index == 2 && value_b.offset == 0); + + relocatable ptr_c = {1, 1}; + ResultMemory result_c = memory_get(&memory, ptr_c); + assert(!result_c.is_error); + relocatable value_c = result_c.value.memory_value.value.relocatable; + assert(value_c.segment_index == 3 && value_c.offset == 0); + runner_free(&runner); printf("OK!\n"); } @@ -44,23 +61,39 @@ void initialize_runner_no_builtins_no_proof_mode_empty_program(void) { struct program program = {0, program_data}; cairo_runner runner = runner_new(program); runner_initialize(&runner); + // Check runner data assert(runner.program_base.segment_index == 0 && runner.program_base.offset == 0); assert(runner.execution_base.segment_index == 1 && runner.execution_base.offset == 0); assert(runner.initial_pc.segment_index == 0 && runner.initial_pc.offset == 0); assert(runner.initial_fp.segment_index == 1 && runner.initial_fp.offset == 2); assert(runner.final_pc.segment_index == 3 && runner.final_pc.offset == 0); + // Check vm data run_context run_context = runner.vm.run_context; assert(run_context.pc.segment_index == 0 && run_context.pc.offset == 0); assert(run_context.ap.segment_index == 1 && run_context.ap.offset == 2); assert(run_context.fp.segment_index == 1 && run_context.fp.offset == 2); + // Check memory + // program segment memory memory = runner.vm.memory; assert(memory.num_segments == 4); relocatable ptr = {0, 0}; ResultMemory result = memory_get(&memory, ptr); assert(result.is_error); + // execution segment + relocatable ptr_b = {1, 0}; + ResultMemory result_b = memory_get(&memory, ptr_b); + assert(!result_b.is_error); + relocatable value_b = result_b.value.memory_value.value.relocatable; + assert(value_b.segment_index == 2 && value_b.offset == 0); + + relocatable ptr_c = {1, 1}; + ResultMemory result_c = memory_get(&memory, ptr_c); + assert(!result_c.is_error); + relocatable value_c = result_c.value.memory_value.value.relocatable; + assert(value_c.segment_index == 3 && value_c.offset == 0); runner_free(&runner); printf("OK!\n"); } From 073b9c243ffa8aefad05ddf86455d2f234656368 Mon Sep 17 00:00:00 2001 From: Federica Date: Mon, 24 Jul 2023 12:44:34 -0300 Subject: [PATCH 40/59] Add error handling to runner init & memory load_data --- src/cairo_runner.c | 44 ++++++++++++++++++++++++++++++++------------ src/cairo_runner.h | 15 ++++++++++++++- src/memory.c | 9 +++++++-- src/memory.h | 2 +- test/memory_tests.c | 6 ++++-- test/runner_tests.c | 8 ++++++-- 6 files changed, 64 insertions(+), 20 deletions(-) diff --git a/src/cairo_runner.c b/src/cairo_runner.c index 8964dce..c2374e5 100644 --- a/src/cairo_runner.c +++ b/src/cairo_runner.c @@ -1,4 +1,5 @@ #include "cairo_runner.h" +#include "memory.h" #include "program.h" #include "relocatable.h" #include "vm.h" @@ -22,19 +23,31 @@ void runner_initialize_segments(cairo_runner *runner) { // Initialize builtin segments } -// Initializes the program segment & initial pc -void runner_initialize_state(cairo_runner *runner, unsigned int entrypoint, CList *stack) { +// Initializes the program segment & initial pc, returns none if ok or memory_error if failure +ResultRunner runner_initialize_state(cairo_runner *runner, unsigned int entrypoint, CList *stack) { runner->initial_pc = runner->program_base; runner->initial_pc.offset += entrypoint; - memory_load_data(&runner->vm.memory, runner->program_base, runner->program.data); - memory_load_data(&runner->vm.memory, runner->execution_base, stack); + ResultMemory load_program_result = + memory_load_data(&runner->vm.memory, runner->program_base, runner->program.data); + if (load_program_result.is_error) { + ResultRunner error = {.is_error = true, .value = {.memory_error = load_program_result.value.error}}; + return error; + } + ResultMemory load_execution_result = memory_load_data(&runner->vm.memory, runner->execution_base, stack); + if (load_execution_result.is_error) { + ResultRunner error = {.is_error = true, .value = {.memory_error = load_execution_result.value.error}}; + return error; + } // Mark data segment as accessed + ResultRunner ok = {.is_error = false, .value = {.none = 0}}; + return ok; } // Initializes memory, initial register values & returns the end pointer (final pc) to run from a given pc offset // (entrypoint) -relocatable runner_initialize_function_entrypoint(cairo_runner *runner, unsigned int entrypoint, CList *stack, - relocatable return_fp) { +// Returns ptr if ok, or memory_error if failure +ResultRunner runner_initialize_function_entrypoint(cairo_runner *runner, unsigned int entrypoint, CList *stack, + relocatable return_fp) { relocatable end = memory_add_segment(&runner->vm.memory); maybe_relocatable return_fp_mr = {.is_felt = false, .value = {.relocatable = return_fp}}; maybe_relocatable end_mr = {.is_felt = false, .value = {.relocatable = end}}; @@ -42,18 +55,24 @@ relocatable runner_initialize_function_entrypoint(cairo_runner *runner, unsigned stack->add(stack, &end_mr); runner->initial_fp.segment_index = runner->execution_base.segment_index; runner->initial_fp.offset = stack->count(stack); - runner_initialize_state(runner, entrypoint, stack); runner->final_pc = end; - return end; + ResultRunner result = runner_initialize_state(runner, entrypoint, stack); + if (result.is_error) { + return result; + } else { + ResultRunner ok = {.is_error = false, .value = {.ptr = end}}; + return ok; + } } // Initializes memory, initial register values & returns the end pointer (final pc) to run from the main entrypoint -relocatable runner_initialize_main_entrypoint(cairo_runner *runner) { +// Returns ptr if ok, or memory_error if failure +ResultRunner runner_initialize_main_entrypoint(cairo_runner *runner) { CList *stack = CList_init(sizeof(maybe_relocatable)); // Handle builtin initial stack // Handle proof-mode specific behaviour relocatable return_fp = memory_add_segment(&runner->vm.memory); - relocatable end = runner_initialize_function_entrypoint(runner, runner->program.main, stack, return_fp); + ResultRunner end = runner_initialize_function_entrypoint(runner, runner->program.main, stack, return_fp); stack->free(stack); return end; } @@ -68,10 +87,11 @@ void runner_initialize_vm(cairo_runner *runner) { } // Performs the intialization step, leaving the runner ready to run a loaded cairo program from a main entrypoint -relocatable runner_initialize(cairo_runner *runner) { +// Returns ptr if ok, or memory_error if failure +ResultRunner runner_initialize(cairo_runner *runner) { // runner_initialize_builtins runner_initialize_segments(runner); - relocatable end = runner_initialize_main_entrypoint(runner); + ResultRunner end = runner_initialize_main_entrypoint(runner); runner_initialize_vm(runner); return end; } diff --git a/src/cairo_runner.h b/src/cairo_runner.h index 9fe8a2d..5ee1b24 100644 --- a/src/cairo_runner.h +++ b/src/cairo_runner.h @@ -17,10 +17,23 @@ typedef struct cairo_runner { } cairo_runner; +// Error Handling + +union ResultRunnerValue { + enum MemoryError memory_error; + relocatable ptr; + int none; +}; + +typedef struct ResultRunner { + union ResultRunnerValue value; + bool is_error; +} ResultRunner; + cairo_runner runner_new(struct program program); void runner_free(cairo_runner *runner); -relocatable runner_initialize(cairo_runner *runner); +ResultRunner runner_initialize(cairo_runner *runner); #endif diff --git a/src/memory.c b/src/memory.c index 13566c2..60fc33f 100644 --- a/src/memory.c +++ b/src/memory.c @@ -67,7 +67,11 @@ relocatable memory_add_segment(memory *memory) { return rel; } -relocatable memory_load_data(memory *memory, relocatable ptr, CList *data) { +ResultMemory memory_load_data(memory *memory, relocatable ptr, CList *data) { + if (ptr.segment_index >= memory->num_segments) { + ResultMemory error = {.is_error = true, .value = {.error = LoadData}}; + return error; + } int size = data->count(data); CList *segment = memory->data->at(memory->data, ptr.segment_index); for (int i = 0; i < size; i++) { @@ -76,7 +80,8 @@ relocatable memory_load_data(memory *memory, relocatable ptr, CList *data) { segment->insert(segment, &new_cell, ptr.offset + i); } ptr.offset += size; - return ptr; + ResultMemory ok = {.is_error = false, .value = {.ptr = ptr}}; + return ok; } void memory_free(memory *mem) { diff --git a/src/memory.h b/src/memory.h index a9b04d6..9cdbb4e 100644 --- a/src/memory.h +++ b/src/memory.h @@ -59,7 +59,7 @@ ResultMemory memory_insert(memory *mem, relocatable ptr, maybe_relocatable value relocatable memory_add_segment(memory *memory); // Inserts the elements in data sequentially from address ptr and returns the next address after the data -relocatable memory_load_data(memory *memory, relocatable ptr, CList *data); +ResultMemory memory_load_data(memory *memory, relocatable ptr, CList *data); // Frees resources used by the memory struct void memory_free(memory *mem); diff --git a/test/memory_tests.c b/test/memory_tests.c index 390f8ac..fdeef18 100644 --- a/test/memory_tests.c +++ b/test/memory_tests.c @@ -112,7 +112,8 @@ void memory_load_data_one_element(void) { data->add(data, &elem); relocatable ptr = {0, 0}; // Load data - relocatable end_ptr = memory_load_data(&mem, ptr, data); + ResultMemory load_result = memory_load_data(&mem, ptr, data); + relocatable end_ptr = load_result.value.ptr; assert(end_ptr.segment_index == 0 && end_ptr.offset == 1); // Check memory ResultMemory result = memory_get(&mem, ptr); @@ -130,7 +131,8 @@ void memory_load_data_empty(void) { struct CList *data = CList_init(sizeof(maybe_relocatable)); relocatable ptr = {0, 0}; // Load data - relocatable end_ptr = memory_load_data(&mem, ptr, data); + ResultMemory load_result = memory_load_data(&mem, ptr, data); + relocatable end_ptr = load_result.value.ptr; assert(end_ptr.segment_index == 0 && end_ptr.offset == 0); // Check memory ResultMemory result = memory_get(&mem, ptr); diff --git a/test/runner_tests.c b/test/runner_tests.c index 3a26b8b..281455b 100644 --- a/test/runner_tests.c +++ b/test/runner_tests.c @@ -16,7 +16,9 @@ void initialize_runner_no_builtins_no_proof_mode_non_empty_program(void) { program_data->add(program_data, &elem); struct program program = {0, program_data}; cairo_runner runner = runner_new(program); - runner_initialize(&runner); + ResultRunner runner_result = runner_initialize(&runner); + assert(!runner_result.is_error); + assert(runner_result.value.ptr.segment_index == 3 && runner_result.value.ptr.offset == 0); // Check runner data assert(runner.program_base.segment_index == 0 && runner.program_base.offset == 0); @@ -60,7 +62,9 @@ void initialize_runner_no_builtins_no_proof_mode_empty_program(void) { struct CList *program_data = CList_init(sizeof(maybe_relocatable)); struct program program = {0, program_data}; cairo_runner runner = runner_new(program); - runner_initialize(&runner); + ResultRunner runner_result = runner_initialize(&runner); + assert(!runner_result.is_error); + assert(runner_result.value.ptr.segment_index == 3 && runner_result.value.ptr.offset == 0); // Check runner data assert(runner.program_base.segment_index == 0 && runner.program_base.offset == 0); From 5ea00bc71e3642ce746801a88d204858c28f4dab Mon Sep 17 00:00:00 2001 From: Federica Date: Mon, 24 Jul 2023 12:45:24 -0300 Subject: [PATCH 41/59] Revert "Add error handling to runner init & memory load_data" This reverts commit 073b9c243ffa8aefad05ddf86455d2f234656368. --- src/cairo_runner.c | 44 ++++++++++++-------------------------------- src/cairo_runner.h | 15 +-------------- src/memory.c | 9 ++------- src/memory.h | 2 +- test/memory_tests.c | 6 ++---- test/runner_tests.c | 8 ++------ 6 files changed, 20 insertions(+), 64 deletions(-) diff --git a/src/cairo_runner.c b/src/cairo_runner.c index c2374e5..8964dce 100644 --- a/src/cairo_runner.c +++ b/src/cairo_runner.c @@ -1,5 +1,4 @@ #include "cairo_runner.h" -#include "memory.h" #include "program.h" #include "relocatable.h" #include "vm.h" @@ -23,31 +22,19 @@ void runner_initialize_segments(cairo_runner *runner) { // Initialize builtin segments } -// Initializes the program segment & initial pc, returns none if ok or memory_error if failure -ResultRunner runner_initialize_state(cairo_runner *runner, unsigned int entrypoint, CList *stack) { +// Initializes the program segment & initial pc +void runner_initialize_state(cairo_runner *runner, unsigned int entrypoint, CList *stack) { runner->initial_pc = runner->program_base; runner->initial_pc.offset += entrypoint; - ResultMemory load_program_result = - memory_load_data(&runner->vm.memory, runner->program_base, runner->program.data); - if (load_program_result.is_error) { - ResultRunner error = {.is_error = true, .value = {.memory_error = load_program_result.value.error}}; - return error; - } - ResultMemory load_execution_result = memory_load_data(&runner->vm.memory, runner->execution_base, stack); - if (load_execution_result.is_error) { - ResultRunner error = {.is_error = true, .value = {.memory_error = load_execution_result.value.error}}; - return error; - } + memory_load_data(&runner->vm.memory, runner->program_base, runner->program.data); + memory_load_data(&runner->vm.memory, runner->execution_base, stack); // Mark data segment as accessed - ResultRunner ok = {.is_error = false, .value = {.none = 0}}; - return ok; } // Initializes memory, initial register values & returns the end pointer (final pc) to run from a given pc offset // (entrypoint) -// Returns ptr if ok, or memory_error if failure -ResultRunner runner_initialize_function_entrypoint(cairo_runner *runner, unsigned int entrypoint, CList *stack, - relocatable return_fp) { +relocatable runner_initialize_function_entrypoint(cairo_runner *runner, unsigned int entrypoint, CList *stack, + relocatable return_fp) { relocatable end = memory_add_segment(&runner->vm.memory); maybe_relocatable return_fp_mr = {.is_felt = false, .value = {.relocatable = return_fp}}; maybe_relocatable end_mr = {.is_felt = false, .value = {.relocatable = end}}; @@ -55,24 +42,18 @@ ResultRunner runner_initialize_function_entrypoint(cairo_runner *runner, unsigne stack->add(stack, &end_mr); runner->initial_fp.segment_index = runner->execution_base.segment_index; runner->initial_fp.offset = stack->count(stack); + runner_initialize_state(runner, entrypoint, stack); runner->final_pc = end; - ResultRunner result = runner_initialize_state(runner, entrypoint, stack); - if (result.is_error) { - return result; - } else { - ResultRunner ok = {.is_error = false, .value = {.ptr = end}}; - return ok; - } + return end; } // Initializes memory, initial register values & returns the end pointer (final pc) to run from the main entrypoint -// Returns ptr if ok, or memory_error if failure -ResultRunner runner_initialize_main_entrypoint(cairo_runner *runner) { +relocatable runner_initialize_main_entrypoint(cairo_runner *runner) { CList *stack = CList_init(sizeof(maybe_relocatable)); // Handle builtin initial stack // Handle proof-mode specific behaviour relocatable return_fp = memory_add_segment(&runner->vm.memory); - ResultRunner end = runner_initialize_function_entrypoint(runner, runner->program.main, stack, return_fp); + relocatable end = runner_initialize_function_entrypoint(runner, runner->program.main, stack, return_fp); stack->free(stack); return end; } @@ -87,11 +68,10 @@ void runner_initialize_vm(cairo_runner *runner) { } // Performs the intialization step, leaving the runner ready to run a loaded cairo program from a main entrypoint -// Returns ptr if ok, or memory_error if failure -ResultRunner runner_initialize(cairo_runner *runner) { +relocatable runner_initialize(cairo_runner *runner) { // runner_initialize_builtins runner_initialize_segments(runner); - ResultRunner end = runner_initialize_main_entrypoint(runner); + relocatable end = runner_initialize_main_entrypoint(runner); runner_initialize_vm(runner); return end; } diff --git a/src/cairo_runner.h b/src/cairo_runner.h index 5ee1b24..9fe8a2d 100644 --- a/src/cairo_runner.h +++ b/src/cairo_runner.h @@ -17,23 +17,10 @@ typedef struct cairo_runner { } cairo_runner; -// Error Handling - -union ResultRunnerValue { - enum MemoryError memory_error; - relocatable ptr; - int none; -}; - -typedef struct ResultRunner { - union ResultRunnerValue value; - bool is_error; -} ResultRunner; - cairo_runner runner_new(struct program program); void runner_free(cairo_runner *runner); -ResultRunner runner_initialize(cairo_runner *runner); +relocatable runner_initialize(cairo_runner *runner); #endif diff --git a/src/memory.c b/src/memory.c index 60fc33f..13566c2 100644 --- a/src/memory.c +++ b/src/memory.c @@ -67,11 +67,7 @@ relocatable memory_add_segment(memory *memory) { return rel; } -ResultMemory memory_load_data(memory *memory, relocatable ptr, CList *data) { - if (ptr.segment_index >= memory->num_segments) { - ResultMemory error = {.is_error = true, .value = {.error = LoadData}}; - return error; - } +relocatable memory_load_data(memory *memory, relocatable ptr, CList *data) { int size = data->count(data); CList *segment = memory->data->at(memory->data, ptr.segment_index); for (int i = 0; i < size; i++) { @@ -80,8 +76,7 @@ ResultMemory memory_load_data(memory *memory, relocatable ptr, CList *data) { segment->insert(segment, &new_cell, ptr.offset + i); } ptr.offset += size; - ResultMemory ok = {.is_error = false, .value = {.ptr = ptr}}; - return ok; + return ptr; } void memory_free(memory *mem) { diff --git a/src/memory.h b/src/memory.h index 9cdbb4e..a9b04d6 100644 --- a/src/memory.h +++ b/src/memory.h @@ -59,7 +59,7 @@ ResultMemory memory_insert(memory *mem, relocatable ptr, maybe_relocatable value relocatable memory_add_segment(memory *memory); // Inserts the elements in data sequentially from address ptr and returns the next address after the data -ResultMemory memory_load_data(memory *memory, relocatable ptr, CList *data); +relocatable memory_load_data(memory *memory, relocatable ptr, CList *data); // Frees resources used by the memory struct void memory_free(memory *mem); diff --git a/test/memory_tests.c b/test/memory_tests.c index fdeef18..390f8ac 100644 --- a/test/memory_tests.c +++ b/test/memory_tests.c @@ -112,8 +112,7 @@ void memory_load_data_one_element(void) { data->add(data, &elem); relocatable ptr = {0, 0}; // Load data - ResultMemory load_result = memory_load_data(&mem, ptr, data); - relocatable end_ptr = load_result.value.ptr; + relocatable end_ptr = memory_load_data(&mem, ptr, data); assert(end_ptr.segment_index == 0 && end_ptr.offset == 1); // Check memory ResultMemory result = memory_get(&mem, ptr); @@ -131,8 +130,7 @@ void memory_load_data_empty(void) { struct CList *data = CList_init(sizeof(maybe_relocatable)); relocatable ptr = {0, 0}; // Load data - ResultMemory load_result = memory_load_data(&mem, ptr, data); - relocatable end_ptr = load_result.value.ptr; + relocatable end_ptr = memory_load_data(&mem, ptr, data); assert(end_ptr.segment_index == 0 && end_ptr.offset == 0); // Check memory ResultMemory result = memory_get(&mem, ptr); diff --git a/test/runner_tests.c b/test/runner_tests.c index 281455b..3a26b8b 100644 --- a/test/runner_tests.c +++ b/test/runner_tests.c @@ -16,9 +16,7 @@ void initialize_runner_no_builtins_no_proof_mode_non_empty_program(void) { program_data->add(program_data, &elem); struct program program = {0, program_data}; cairo_runner runner = runner_new(program); - ResultRunner runner_result = runner_initialize(&runner); - assert(!runner_result.is_error); - assert(runner_result.value.ptr.segment_index == 3 && runner_result.value.ptr.offset == 0); + runner_initialize(&runner); // Check runner data assert(runner.program_base.segment_index == 0 && runner.program_base.offset == 0); @@ -62,9 +60,7 @@ void initialize_runner_no_builtins_no_proof_mode_empty_program(void) { struct CList *program_data = CList_init(sizeof(maybe_relocatable)); struct program program = {0, program_data}; cairo_runner runner = runner_new(program); - ResultRunner runner_result = runner_initialize(&runner); - assert(!runner_result.is_error); - assert(runner_result.value.ptr.segment_index == 3 && runner_result.value.ptr.offset == 0); + runner_initialize(&runner); // Check runner data assert(runner.program_base.segment_index == 0 && runner.program_base.offset == 0); From b3668292d486eefa2196e5825b232dafa66dedc6 Mon Sep 17 00:00:00 2001 From: Federica Date: Mon, 24 Jul 2023 12:51:50 -0300 Subject: [PATCH 42/59] add error handling to memory_load_data --- src/memory.c | 9 +++++++-- src/memory.h | 7 ++++--- test/memory_tests.c | 6 ++++-- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/memory.c b/src/memory.c index 13566c2..60fc33f 100644 --- a/src/memory.c +++ b/src/memory.c @@ -67,7 +67,11 @@ relocatable memory_add_segment(memory *memory) { return rel; } -relocatable memory_load_data(memory *memory, relocatable ptr, CList *data) { +ResultMemory memory_load_data(memory *memory, relocatable ptr, CList *data) { + if (ptr.segment_index >= memory->num_segments) { + ResultMemory error = {.is_error = true, .value = {.error = LoadData}}; + return error; + } int size = data->count(data); CList *segment = memory->data->at(memory->data, ptr.segment_index); for (int i = 0; i < size; i++) { @@ -76,7 +80,8 @@ relocatable memory_load_data(memory *memory, relocatable ptr, CList *data) { segment->insert(segment, &new_cell, ptr.offset + i); } ptr.offset += size; - return ptr; + ResultMemory ok = {.is_error = false, .value = {.ptr = ptr}}; + return ok; } void memory_free(memory *mem) { diff --git a/src/memory.h b/src/memory.h index a9b04d6..2ef1ce0 100644 --- a/src/memory.h +++ b/src/memory.h @@ -49,17 +49,18 @@ typedef struct ResultMemory { // Creates a new empty memory memory memory_new(void); -// Fetches a value from memory indicated by ptr +// Fetches a value from memory indicated by ptr, returns a maybe_relocatable ResultMemory memory_get(memory *mem, relocatable ptr); -// Inserts value into memory at address ptr +// Inserts value into memory at address ptr, returns none ResultMemory memory_insert(memory *mem, relocatable ptr, maybe_relocatable value); // Adds a memory segment relocatable memory_add_segment(memory *memory); // Inserts the elements in data sequentially from address ptr and returns the next address after the data -relocatable memory_load_data(memory *memory, relocatable ptr, CList *data); +// returns ptr +ResultMemory memory_load_data(memory *memory, relocatable ptr, CList *data); // Frees resources used by the memory struct void memory_free(memory *mem); diff --git a/test/memory_tests.c b/test/memory_tests.c index 390f8ac..fdeef18 100644 --- a/test/memory_tests.c +++ b/test/memory_tests.c @@ -112,7 +112,8 @@ void memory_load_data_one_element(void) { data->add(data, &elem); relocatable ptr = {0, 0}; // Load data - relocatable end_ptr = memory_load_data(&mem, ptr, data); + ResultMemory load_result = memory_load_data(&mem, ptr, data); + relocatable end_ptr = load_result.value.ptr; assert(end_ptr.segment_index == 0 && end_ptr.offset == 1); // Check memory ResultMemory result = memory_get(&mem, ptr); @@ -130,7 +131,8 @@ void memory_load_data_empty(void) { struct CList *data = CList_init(sizeof(maybe_relocatable)); relocatable ptr = {0, 0}; // Load data - relocatable end_ptr = memory_load_data(&mem, ptr, data); + ResultMemory load_result = memory_load_data(&mem, ptr, data); + relocatable end_ptr = load_result.value.ptr; assert(end_ptr.segment_index == 0 && end_ptr.offset == 0); // Check memory ResultMemory result = memory_get(&mem, ptr); From 59aa6cdab52fb3f461f7b5299d8bb27705cba73e Mon Sep 17 00:00:00 2001 From: Federica Date: Mon, 24 Jul 2023 12:55:09 -0300 Subject: [PATCH 43/59] Add err case result --- test/memory_tests.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/test/memory_tests.c b/test/memory_tests.c index fdeef18..ef3f183 100644 --- a/test/memory_tests.c +++ b/test/memory_tests.c @@ -113,6 +113,7 @@ void memory_load_data_one_element(void) { relocatable ptr = {0, 0}; // Load data ResultMemory load_result = memory_load_data(&mem, ptr, data); + assert(!load_result.is_error); relocatable end_ptr = load_result.value.ptr; assert(end_ptr.segment_index == 0 && end_ptr.offset == 1); // Check memory @@ -132,6 +133,7 @@ void memory_load_data_empty(void) { relocatable ptr = {0, 0}; // Load data ResultMemory load_result = memory_load_data(&mem, ptr, data); + assert(!load_result.is_error); relocatable end_ptr = load_result.value.ptr; assert(end_ptr.segment_index == 0 && end_ptr.offset == 0); // Check memory @@ -141,6 +143,18 @@ void memory_load_data_empty(void) { printf("OK!\n"); } +void memory_load_data_err_unallocated_segment(void) { + // Initialize memory + memory mem = memory_new(); + // Initialize data to load + struct CList *data = CList_init(sizeof(maybe_relocatable)); + relocatable ptr = {0, 0}; + // Load data + ResultMemory load_result = memory_load_data(&mem, ptr, data); + assert(load_result.is_error); + assert(load_result.value.error == LoadData); +} + void memory_add_segment_ok(void) { // Initialize memory memory mem = memory_new(); @@ -177,6 +191,9 @@ void memory_tests(void) { printf("Test: memory_load_data_one_element \n"); memory_load_data_one_element(); printf("--------------------------------- \n"); + printf("Test: memory_load_data_err_unallocated_segment \n"); + memory_load_data_err_unallocated_segment(); + printf("--------------------------------- \n"); printf("Test: memory_add_segment_ok \n"); memory_add_segment_ok(); } From 1641508701a4345564bda82102ce1b896b935b6e Mon Sep 17 00:00:00 2001 From: Federica Date: Mon, 24 Jul 2023 13:00:14 -0300 Subject: [PATCH 44/59] Add warning, move comment to header --- src/cairo_runner.c | 7 ++++++- src/cairo_runner.h | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/cairo_runner.c b/src/cairo_runner.c index 8964dce..0782bd1 100644 --- a/src/cairo_runner.c +++ b/src/cairo_runner.c @@ -23,9 +23,13 @@ void runner_initialize_segments(cairo_runner *runner) { } // Initializes the program segment & initial pc +// Warning: Can fail if used outside of runner_initialize void runner_initialize_state(cairo_runner *runner, unsigned int entrypoint, CList *stack) { runner->initial_pc = runner->program_base; runner->initial_pc.offset += entrypoint; + // We ignore the error cases when loading data as these cases are unreachable when called after + // runner_initialize_segments We can safely ignore them as long as any public function that calls this function + // calls runner_initialize_segments before memory_load_data(&runner->vm.memory, runner->program_base, runner->program.data); memory_load_data(&runner->vm.memory, runner->execution_base, stack); // Mark data segment as accessed @@ -33,6 +37,7 @@ void runner_initialize_state(cairo_runner *runner, unsigned int entrypoint, CLis // Initializes memory, initial register values & returns the end pointer (final pc) to run from a given pc offset // (entrypoint) +// Warning: Can fail if runner_initialize_segments is not called before relocatable runner_initialize_function_entrypoint(cairo_runner *runner, unsigned int entrypoint, CList *stack, relocatable return_fp) { relocatable end = memory_add_segment(&runner->vm.memory); @@ -48,6 +53,7 @@ relocatable runner_initialize_function_entrypoint(cairo_runner *runner, unsigned } // Initializes memory, initial register values & returns the end pointer (final pc) to run from the main entrypoint +// Warning: Can fail if runner_initialize_segments is not called before relocatable runner_initialize_main_entrypoint(cairo_runner *runner) { CList *stack = CList_init(sizeof(maybe_relocatable)); // Handle builtin initial stack @@ -67,7 +73,6 @@ void runner_initialize_vm(cairo_runner *runner) { // Apply validation rules to memory } -// Performs the intialization step, leaving the runner ready to run a loaded cairo program from a main entrypoint relocatable runner_initialize(cairo_runner *runner) { // runner_initialize_builtins runner_initialize_segments(runner); diff --git a/src/cairo_runner.h b/src/cairo_runner.h index 9fe8a2d..5bd7e48 100644 --- a/src/cairo_runner.h +++ b/src/cairo_runner.h @@ -21,6 +21,7 @@ cairo_runner runner_new(struct program program); void runner_free(cairo_runner *runner); +// Performs the intialization step, leaving the runner ready to run a loaded cairo program from a main entrypoint relocatable runner_initialize(cairo_runner *runner); #endif From 4a0fce9ba6518cdd9bdd6992de5b4e51d9998fb7 Mon Sep 17 00:00:00 2001 From: Federica Date: Mon, 24 Jul 2023 13:03:05 -0300 Subject: [PATCH 45/59] Move comments to header --- src/cairo_runner.c | 2 -- src/cairo_runner.h | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cairo_runner.c b/src/cairo_runner.c index 0782bd1..8829633 100644 --- a/src/cairo_runner.c +++ b/src/cairo_runner.c @@ -3,14 +3,12 @@ #include "relocatable.h" #include "vm.h" -// Creates a new, empty cairo_runner cairo_runner runner_new(struct program program) { virtual_machine vm = vm_new(); cairo_runner runner = {program, vm, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}; return runner; } -// Frees resources used by the cairo_runner struct void runner_free(cairo_runner *runner) { memory_free(&runner->vm.memory); } // Creates program, execution and builtin segments diff --git a/src/cairo_runner.h b/src/cairo_runner.h index 5bd7e48..cd4580f 100644 --- a/src/cairo_runner.h +++ b/src/cairo_runner.h @@ -17,8 +17,10 @@ typedef struct cairo_runner { } cairo_runner; +// Creates a new, empty cairo_runner cairo_runner runner_new(struct program program); +// Frees resources used by the cairo_runner struct void runner_free(cairo_runner *runner); // Performs the intialization step, leaving the runner ready to run a loaded cairo program from a main entrypoint From 364bb882192beffaffb917048c0bd4a065872a95 Mon Sep 17 00:00:00 2001 From: Federica Date: Mon, 24 Jul 2023 13:08:39 -0300 Subject: [PATCH 46/59] Free program --- src/cairo_runner.c | 5 ++++- src/program.c | 3 +++ src/program.h | 3 +++ 3 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 src/program.c diff --git a/src/cairo_runner.c b/src/cairo_runner.c index 8829633..44a80ce 100644 --- a/src/cairo_runner.c +++ b/src/cairo_runner.c @@ -9,7 +9,10 @@ cairo_runner runner_new(struct program program) { return runner; } -void runner_free(cairo_runner *runner) { memory_free(&runner->vm.memory); } +void runner_free(cairo_runner *runner) { + memory_free(&runner->vm.memory); + program_free(&runner->program); +} // Creates program, execution and builtin segments void runner_initialize_segments(cairo_runner *runner) { diff --git a/src/program.c b/src/program.c new file mode 100644 index 0000000..bd59a1d --- /dev/null +++ b/src/program.c @@ -0,0 +1,3 @@ +#include "program.h" + +void program_free(struct program *program) { program->data->free(program->data); } diff --git a/src/program.h b/src/program.h index e2b9b92..46f6242 100644 --- a/src/program.h +++ b/src/program.h @@ -8,4 +8,7 @@ struct program { CList *data; }; +// Frees resources used by program struct +void program_free(struct program *program); + #endif From fd379ad11567efcbe583d3bc7632621869ef999a Mon Sep 17 00:00:00 2001 From: Federica Date: Mon, 24 Jul 2023 13:10:32 -0300 Subject: [PATCH 47/59] Free data used in load_data tests --- test/memory_tests.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/memory_tests.c b/test/memory_tests.c index ef3f183..5194c18 100644 --- a/test/memory_tests.c +++ b/test/memory_tests.c @@ -121,6 +121,7 @@ void memory_load_data_one_element(void) { assert(!result.is_error); assert(maybe_relocatable_equal(result.value.memory_value, elem)); memory_free(&mem); + data->free(data); printf("OK!\n"); } @@ -140,6 +141,7 @@ void memory_load_data_empty(void) { ResultMemory result = memory_get(&mem, ptr); assert(result.is_error); memory_free(&mem); + data->free(data); printf("OK!\n"); } @@ -153,6 +155,8 @@ void memory_load_data_err_unallocated_segment(void) { ResultMemory load_result = memory_load_data(&mem, ptr, data); assert(load_result.is_error); assert(load_result.value.error == LoadData); + data->free(data); + memory_free(&mem); } void memory_add_segment_ok(void) { From 34d73ecd2097a2ea5fca2d3f2abe4fd5cc8ccbfe Mon Sep 17 00:00:00 2001 From: Federica Date: Mon, 24 Jul 2023 13:28:53 -0300 Subject: [PATCH 48/59] Swap clear for free --- src/memory.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/memory.c b/src/memory.c index 60fc33f..faa7a69 100644 --- a/src/memory.c +++ b/src/memory.c @@ -90,5 +90,5 @@ void memory_free(memory *mem) { CList *segment = mem->data->at(mem->data, i); segment->clear(segment); } - mem->data->clear(mem->data); + mem->data->free(mem->data); } From 6ba7cdfaae003e686a4209cca52d480168cd38bc Mon Sep 17 00:00:00 2001 From: Milton Date: Mon, 24 Jul 2023 17:18:37 -0300 Subject: [PATCH 49/59] Execution functions --- src/relocatable.c | 33 +++++++++++++++++++++++++++++++++ src/relocatable.h | 3 ++- src/run_context.c | 22 ++++++++++++++++++++++ src/run_context.h | 4 ++++ src/utils.c | 7 +++++++ src/utils.h | 1 + src/vm.c | 16 ++++++++++++---- src/vm.h | 35 +++++++++++++++++++++++++++++++++++ 8 files changed, 116 insertions(+), 5 deletions(-) create mode 100644 src/run_context.c diff --git a/src/relocatable.c b/src/relocatable.c index 595f15f..3800b20 100644 --- a/src/relocatable.c +++ b/src/relocatable.c @@ -1,6 +1,39 @@ #include "relocatable.h" #include "utils.h" +// -------------------------------- +// Sign operations for relocatable +// -------------------------------- + +// TODO: fix this to thrown an error if off < other +relocatable sub_relocatable(relocatable a, uint64_t other) { + unsigned int offset = a.offset; + unsigned int new_offset = offset - other; + relocatable result = {.segment_index = a.segment_index, .offset = new_offset}; + + return result; +} + +uint64_t checked_add(uint64_t a, uint64_t b) { + uint64_t res = a + b; + if (res <= a || res <= b) + return 0; + else + return res; +} + +// TODO: fix this to thrown an error. if add overflows +relocatable add_relocatable(relocatable a, uint64_t other) { + unsigned int off = a.offset; + uint64_t check_sum = checked_add(off, other); + relocatable res = {.segment_index = a.segment_index, .offset = check_sum}; + return res; +} + +// ----------------------------------- +// operations for maybe_relocatable +// ----------------------------------- + bool maybe_relocatable_equal(maybe_relocatable a, maybe_relocatable b) { if (a.is_felt && b.is_felt) { return felt_equal(a.value.felt, b.value.felt); diff --git a/src/relocatable.h b/src/relocatable.h index 35d3969..a72faad 100644 --- a/src/relocatable.h +++ b/src/relocatable.h @@ -21,7 +21,8 @@ typedef struct maybe_relocatable { } maybe_relocatable; bool maybe_relocatable_equal(maybe_relocatable a, maybe_relocatable b); - +relocatable sub_relocatable(relocatable a, uint64_t other); +relocatable add_relocatable(relocatable a, uint64_t other); maybe_relocatable maybe_relocatable_from_felt_limbs(limb_t *felt); #endif diff --git a/src/run_context.c b/src/run_context.c new file mode 100644 index 0000000..b926eb1 --- /dev/null +++ b/src/run_context.c @@ -0,0 +1,22 @@ +#include "run_context.h" + +relocatable compute_dst_addr(run_context run_ctx, Instruction instr) { + relocatable base_addr; + switch (instr.dst_register) { + case REG_AP: { + base_addr = {.segment_index = 1, .offset = run_ctx.ap}; + } break; + default: { + base_addr = {.segment_index = 1, .offset = run_ctx.fp}; + } break; + } + + relocatable res_base_addr; + if (instr.off0 < 0) { + res_base_addr = sub_relocatable(base_addr, (uint64_t)absolute(instr.off0)); + } else { + res_base_addr = add_relocatable(base_addr, (uint64_t)instr.off0); + } + + return res_base_addr; +} diff --git a/src/run_context.h b/src/run_context.h index c6fd35a..f0d2d3b 100644 --- a/src/run_context.h +++ b/src/run_context.h @@ -1,7 +1,9 @@ #ifndef RUN_CONTEXT_H #define RUN_CONTEXT_H +#include "instruction.h" #include "relocatable.h" +#include "utils.h" typedef struct run_context { relocatable pc; @@ -9,4 +11,6 @@ typedef struct run_context { relocatable fp; } run_context; +relocatable compute_dst_addr(run_context run_ctx, Instruction instr); + #endif diff --git a/src/utils.c b/src/utils.c index fa77de7..ed1887e 100644 --- a/src/utils.c +++ b/src/utils.c @@ -1,5 +1,12 @@ #include "utils.h" +int64_t absolute(int64_t a) { + if (a < 0) + return (-1) * a; + else + return a; +} + bool felt_equal(felt_t a, felt_t b) { return (a[0] == b[0] && a[1] == b[1] && a[2] == b[2] && a[3] == b[3]); } // ------------ diff --git a/src/utils.h b/src/utils.h index eae9747..a417637 100644 --- a/src/utils.h +++ b/src/utils.h @@ -7,6 +7,7 @@ #include bool felt_equal(felt_t a, felt_t b); +int64_t absolute(int64_t a); uint8_t *u64_to_le_bytes(uint64_t value, uint8_t *buffer_bytes); uint8_t *u64_to_be_bytes(uint64_t value, uint8_t *buffer_bytes); diff --git a/src/vm.c b/src/vm.c index bf5751b..1bfce7f 100644 --- a/src/vm.c +++ b/src/vm.c @@ -5,16 +5,24 @@ virtual_machine vm_new(void) { return vm; } -vm_result run_instruction(Instruction instr) { +computed_operands_res compute_operands(virtual_machine vm, Instruction instr) { + relocatable dst_addr = compute_dst_addr(vm.run_context, instr); + ResultMemory mem_res = memory_get(&vm.memory, dst_addr); +} + +vm_result run_instruction(virtual_machine vm, Instruction instr) { - int64_t e = instr.off0; + computed_operands_res com_op_res = compute_operands(vm, instr); + if (com_op_res.is_error) { + VirtualMachineError err = com_op_res.error; + vm_result res = {.is_ok = false, .error = err}; + return res; + } vm_result res = { .is_ok = true, .error = None, }; - if (e == 1) - return res; return res; } diff --git a/src/vm.h b/src/vm.h index 0ccc5d9..6b6451f 100644 --- a/src/vm.h +++ b/src/vm.h @@ -15,7 +15,42 @@ typedef struct { memory memory; } virtual_machine; +// --------------------- +// execution structures +// --------------------- + +typedef struct { + maybe_relocatable dst; + memory_cell res; + maybe_relocatable op0; + maybe_relocatable op1; +} operands; + +typedef struct { + relocatable dst_addr; + relocatable op0_addr; + relocatable op1_addr; +} operands_address; + +typedef struct { + operands oprs; + operands_address op_addrs; + uint8_t deduced_operands; +} computed_operands; + +typedef struct { + computed_operands value; + VirtualMachineError error; + bool is_error; +} computed_operands_res; + +// --------------------- +// VM functions +// --------------------- + // Creates a new, empty virtual_machine virtual_machine vm_new(void); +// executes an instruction in the vm +vm_result run_instruction(virtual_machine vm, Instruction instr); #endif From 540b21bf5ff03ab967483d2a85b2b011b5ed3b9d Mon Sep 17 00:00:00 2001 From: Milton Date: Tue, 25 Jul 2023 12:37:57 -0300 Subject: [PATCH 50/59] Add compute operands functions --- computed_operands_res | 0 src/instruction.h | 1 + src/run_context.c | 53 +++++++++++++++++++++++++++++++++++++++++++ src/run_context.h | 2 ++ src/vm.c | 17 +++++++++++++- src/vm.h | 8 +++++-- 6 files changed, 78 insertions(+), 3 deletions(-) create mode 100644 computed_operands_res diff --git a/computed_operands_res b/computed_operands_res new file mode 100644 index 0000000..e69de29 diff --git a/src/instruction.h b/src/instruction.h index 519d675..d92a81d 100644 --- a/src/instruction.h +++ b/src/instruction.h @@ -88,6 +88,7 @@ enum VirtualMachineError { InvalidRes, InvalidOpcode, InvalidApUpdate, + MemoryError, None }; diff --git a/src/run_context.c b/src/run_context.c index d0a762f..28b8828 100644 --- a/src/run_context.c +++ b/src/run_context.c @@ -1,4 +1,5 @@ #include "run_context.h" +#include "instruction.h" relocatable compute_dst_addr(run_context run_ctx, Instruction instr) { struct relocatable base_addr; @@ -20,3 +21,55 @@ relocatable compute_dst_addr(run_context run_ctx, Instruction instr) { return res_base_addr; } + +relocatable compute_op0_addr(run_context run_ctx, Instruction instr) { + struct relocatable base_addr; + switch (instr.op0_register) { + case REG_AP: { + base_addr = run_ctx.ap; + } break; + default: { + base_addr = run_ctx.fp; + } break; + } + + relocatable res_base_addr; + if (instr.off0 < 0) { + res_base_addr = sub_relocatable(base_addr, (uint64_t)absolute(instr.off1)); + } else { + res_base_addr = add_relocatable(base_addr, (uint64_t)instr.off1); + } + return res_base_addr; +} + +relocatable compute_op1_addr(run_context run_ctx, Instruction instr, maybe_relocatable op0) { + relocatable base_addr; + switch (instr.op1_addr) { + case OP_FP: + base_addr = run_ctx.fp; + break; + case OP_AP: + base_addr = run_ctx.ap; + break; + case Imm: + if (instr.off2 == 1) + base_addr = run_ctx.pc; + break; + case Op0: { + if (!op0.is_felt) { + base_addr = op0.value.relocatable; + } + } break; + default: + base_addr = {-1, -1}; + break; + } + + relocatable res_base_addr; + if (instr.off2 < 0) { + res_base_addr = sub_relocatable(base_addr, (uint64_t)absolute(instr.off2)); + } else { + res_base_addr = add_relocatable(base_addr, (uint64_t)instr.off2); + } + return res_base_addr; +} diff --git a/src/run_context.h b/src/run_context.h index f0d2d3b..9fcde5d 100644 --- a/src/run_context.h +++ b/src/run_context.h @@ -12,5 +12,7 @@ typedef struct run_context { } run_context; relocatable compute_dst_addr(run_context run_ctx, Instruction instr); +relocatable compute_op0_addr(run_context run_ctx, Instruction instr); +relocatable compute_op1_addr(run_context run_ctx, Instruction instr, maybe_relocatable op0); #endif diff --git a/src/vm.c b/src/vm.c index 1bfce7f..9e4f297 100644 --- a/src/vm.c +++ b/src/vm.c @@ -1,4 +1,6 @@ #include "vm.h" +#include "memory.h" +#include "run_context.h" virtual_machine vm_new(void) { virtual_machine vm = {{{0, 0}, {0, 0}, {0, 0}}, memory_new()}; @@ -8,13 +10,26 @@ virtual_machine vm_new(void) { computed_operands_res compute_operands(virtual_machine vm, Instruction instr) { relocatable dst_addr = compute_dst_addr(vm.run_context, instr); ResultMemory mem_res = memory_get(&vm.memory, dst_addr); + if (mem_res.is_error) { + computed_operands_res res = {.value = {MemoryError}, .is_error = true}; + return res; + } + + relocatable op0_addr = compute_op0_addr(vm.run_context, instr); + ResultMemory op0_op = memory_get(&vm.memory, op0_addr); + if (op0_op.is_error) { + computed_operands_res res = {.value = {MemoryError}, .is_error = true}; + return res; + } + + relocatable op1_addr = compute_op1_addr(vm.run_context, op0_op); } vm_result run_instruction(virtual_machine vm, Instruction instr) { computed_operands_res com_op_res = compute_operands(vm, instr); if (com_op_res.is_error) { - VirtualMachineError err = com_op_res.error; + VirtualMachineError err = com_op_res.value.error; vm_result res = {.is_ok = false, .error = err}; return res; } diff --git a/src/vm.h b/src/vm.h index 6b6451f..7857b9b 100644 --- a/src/vm.h +++ b/src/vm.h @@ -38,9 +38,13 @@ typedef struct { uint8_t deduced_operands; } computed_operands; -typedef struct { - computed_operands value; +typedef union { + computed_operands ops; VirtualMachineError error; +} computed_operands_value; + +typedef struct { + computed_operands_value value; bool is_error; } computed_operands_res; From 8dee43a6d943b31273e6abc4c8ac13f9aaa03484 Mon Sep 17 00:00:00 2001 From: Milton Date: Tue, 25 Jul 2023 13:00:29 -0300 Subject: [PATCH 51/59] Decude op1 --- src/run_context.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/run_context.c b/src/run_context.c index 28b8828..6083a03 100644 --- a/src/run_context.c +++ b/src/run_context.c @@ -60,9 +60,9 @@ relocatable compute_op1_addr(run_context run_ctx, Instruction instr, maybe_reloc base_addr = op0.value.relocatable; } } break; - default: - base_addr = {-1, -1}; - break; + default: { + base_addr = {.segment_index = 0, .offset = 0}; + } break; } relocatable res_base_addr; From c866258c27657aaab6f4e348e712f339a6fabbe1 Mon Sep 17 00:00:00 2001 From: Milton Date: Tue, 25 Jul 2023 14:13:22 -0300 Subject: [PATCH 52/59] Fix error on declaration and add types to enum --- src/memory.c | 24 ++++++++++++------------ src/memory.h | 4 +++- src/run_context.c | 2 +- src/vm.c | 13 ++++++++----- 4 files changed, 24 insertions(+), 19 deletions(-) diff --git a/src/memory.c b/src/memory.c index faa7a69..20a408a 100644 --- a/src/memory.c +++ b/src/memory.c @@ -12,20 +12,20 @@ ResultMemory memory_get(memory *mem, relocatable ptr) { int index = ptr.segment_index; int offset = ptr.offset; if (index >= mem->data->count(mem->data)) { - ResultMemory error = {.is_error = true, .value = {.error = Get}}; + ResultMemory error = {.type = Err, .value = {.error = Get}}; return error; } CList *segment = mem->data->at(mem->data, ptr.segment_index); if (offset >= segment->count(segment)) { - ResultMemory error = {.is_error = true, .value = {.error = Get}}; + ResultMemory error = {.type = Err, .value = {.error = Get}}; return error; } memory_cell *cell = segment->at(segment, ptr.offset); if (cell->is_some) { - ResultMemory ok = {.is_error = false, .value = {.memory_value = cell->memory_value.value}}; + ResultMemory ok = {.type = false, .value = {.memory_value = cell->memory_value.value}}; return ok; } - ResultMemory error = {.is_error = true, .value = {.error = Get}}; + ResultMemory error = {.type = Err, .value = {.error = Get}}; return error; } @@ -33,7 +33,7 @@ ResultMemory memory_insert(memory *mem, relocatable ptr, maybe_relocatable value int index = ptr.segment_index; int offset = ptr.segment_index; if (index >= mem->data->count(mem->data)) { - ResultMemory error = {.is_error = true, .value = {.error = Insert}}; + ResultMemory error = {.type = Err, .value = {.error = Insert}}; return error; } CList *segment = mem->data->at(mem->data, ptr.segment_index); @@ -44,18 +44,18 @@ ResultMemory memory_insert(memory *mem, relocatable ptr, maybe_relocatable value } ResultMemory get_result = memory_get(mem, ptr); // Check for possible ovewrites - if (!get_result.is_error) { + if (!get_result.type) { if (maybe_relocatable_equal(get_result.value.memory_value, value)) { - ResultMemory ok = {.is_error = false, .value = {.none = 0}}; + ResultMemory ok = {.type = Int, .value = {.none = 0}}; return ok; } else { - ResultMemory error = {.is_error = true, .value = {.error = Insert}}; + ResultMemory error = {.type = Err, .value = {.error = Insert}}; return error; } } - memory_cell new_cell = {.is_some = true, .memory_value = {.value = value}}; + memory_cell new_cell = {.is_some = Err, .memory_value = {.value = value}}; segment->insert(segment, &new_cell, ptr.offset); - ResultMemory ok = {.is_error = false, .value = {.none = 0}}; + ResultMemory ok = {.type = Int, .value = {.none = 0}}; return ok; } @@ -69,7 +69,7 @@ relocatable memory_add_segment(memory *memory) { ResultMemory memory_load_data(memory *memory, relocatable ptr, CList *data) { if (ptr.segment_index >= memory->num_segments) { - ResultMemory error = {.is_error = true, .value = {.error = LoadData}}; + ResultMemory error = {.type = Err, .value = {.error = LoadData}}; return error; } int size = data->count(data); @@ -80,7 +80,7 @@ ResultMemory memory_load_data(memory *memory, relocatable ptr, CList *data) { segment->insert(segment, &new_cell, ptr.offset + i); } ptr.offset += size; - ResultMemory ok = {.is_error = false, .value = {.ptr = ptr}}; + ResultMemory ok = {.type = Relocatable, .value = {.ptr = ptr}}; return ok; } diff --git a/src/memory.h b/src/memory.h index 2ef1ce0..a0b564c 100644 --- a/src/memory.h +++ b/src/memory.h @@ -32,6 +32,8 @@ enum MemoryError { LoadData, }; +enum ResultMemoryType { Felt, Relocatable, MaybeRelocatable, Int, Err }; + union ResultMemoryValue { enum MemoryError error; maybe_relocatable memory_value; @@ -40,7 +42,7 @@ union ResultMemoryValue { }; typedef struct ResultMemory { - bool is_error; + enum ResultMemoryType type; union ResultMemoryValue value; } ResultMemory; diff --git a/src/run_context.c b/src/run_context.c index 6083a03..3289a80 100644 --- a/src/run_context.c +++ b/src/run_context.c @@ -61,7 +61,7 @@ relocatable compute_op1_addr(run_context run_ctx, Instruction instr, maybe_reloc } } break; default: { - base_addr = {.segment_index = 0, .offset = 0}; + base_addr = (relocatable){.segment_index = 0, .offset = 0}; } break; } diff --git a/src/vm.c b/src/vm.c index 9e4f297..eeb8be4 100644 --- a/src/vm.c +++ b/src/vm.c @@ -10,19 +10,22 @@ virtual_machine vm_new(void) { computed_operands_res compute_operands(virtual_machine vm, Instruction instr) { relocatable dst_addr = compute_dst_addr(vm.run_context, instr); ResultMemory mem_res = memory_get(&vm.memory, dst_addr); - if (mem_res.is_error) { - computed_operands_res res = {.value = {MemoryError}, .is_error = true}; + if (mem_res.type == Err) { + computed_operands_res res = {.value = { .error = MemoryError}, .is_error = true}; return res; } relocatable op0_addr = compute_op0_addr(vm.run_context, instr); ResultMemory op0_op = memory_get(&vm.memory, op0_addr); - if (op0_op.is_error) { - computed_operands_res res = {.value = {MemoryError}, .is_error = true}; + if (op0_op.type == Err) { + computed_operands_res res = {.value = {.error = MemoryError}, .is_error = true}; return res; } - relocatable op1_addr = compute_op1_addr(vm.run_context, op0_op); + relocatable op1_addr = compute_op1_addr(vm.run_context, instr, op0_op.value.memory_value); + ResultMemory op1_op = memory_get(&vm.memory, op1_addr); + + uint8_t deduced_operands = 0; } vm_result run_instruction(virtual_machine vm, Instruction instr) { From cbeb378e05c48d5912845ba0e0908049ade77e83 Mon Sep 17 00:00:00 2001 From: Milton Date: Wed, 26 Jul 2023 07:59:14 -0300 Subject: [PATCH 53/59] maybe reloc --- src/vm.c | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/src/vm.c b/src/vm.c index eeb8be4..d3bc950 100644 --- a/src/vm.c +++ b/src/vm.c @@ -11,7 +11,7 @@ computed_operands_res compute_operands(virtual_machine vm, Instruction instr) { relocatable dst_addr = compute_dst_addr(vm.run_context, instr); ResultMemory mem_res = memory_get(&vm.memory, dst_addr); if (mem_res.type == Err) { - computed_operands_res res = {.value = { .error = MemoryError}, .is_error = true}; + computed_operands_res res = {.value = {.error = MemoryError}, .is_error = true}; return res; } @@ -25,22 +25,26 @@ computed_operands_res compute_operands(virtual_machine vm, Instruction instr) { relocatable op1_addr = compute_op1_addr(vm.run_context, instr, op0_op.value.memory_value); ResultMemory op1_op = memory_get(&vm.memory, op1_addr); + felt_t value; + from(value, 0); + maybe_relocatable res = {.is_felt = false, .value = {value[0], value[1], value[2], value[3]}}; uint8_t deduced_operands = 0; } -vm_result run_instruction(virtual_machine vm, Instruction instr) { +// TODO: uncomment once all functions are done +// vm_result run_instruction(virtual_machine vm, Instruction instr) { - computed_operands_res com_op_res = compute_operands(vm, instr); - if (com_op_res.is_error) { - VirtualMachineError err = com_op_res.value.error; - vm_result res = {.is_ok = false, .error = err}; - return res; - } +// computed_operands_res com_op_res = compute_operands(vm, instr); +// if (com_op_res.is_error) { +// VirtualMachineError err = com_op_res.value.error; +// vm_result res = {.is_ok = false, .error = err}; +// return res; +// } - vm_result res = { - .is_ok = true, - .error = None, - }; +// vm_result res = { +// .is_ok = true, +// .error = None, +// }; - return res; -} +// return res; +// } From 55db074172e2557e9e7f1ca14ad40ab5d45d786e Mon Sep 17 00:00:00 2001 From: Milton Date: Wed, 26 Jul 2023 10:14:52 -0300 Subject: [PATCH 54/59] add value --- src/utils.c | 17 +++++++++ src/vm.c | 105 +++++++++++++++++++++++++++++++++++----------------- src/vm.h | 1 + 3 files changed, 90 insertions(+), 33 deletions(-) diff --git a/src/utils.c b/src/utils.c index ed1887e..2548da5 100644 --- a/src/utils.c +++ b/src/utils.c @@ -1,4 +1,21 @@ #include "utils.h" +#include "relocatable.h" + + + +maybe_relocatable add_maybe_relocatable(maybe_relocatable a, maybe_relocatable b){ + if(a.is_felt && b.is_felt) { + + felt_t f1 = {a.value.felt[0], a.value.felt[1], a.value.felt[2], a.value.felt[3]}; + felt_t f2 = {b.value.felt[0], b.value.felt[1], b.value.felt[2], b.value.felt[3]}; + felt_t result; + add(f1, f2, result); + maybe_relocatable res = {.is_felt = true, .value = {.felt = {result[0], result[1], result[2], result[3]}}}; + return res; + } +} + + int64_t absolute(int64_t a) { if (a < 0) diff --git a/src/vm.c b/src/vm.c index f0591a3..c3c5b8f 100644 --- a/src/vm.c +++ b/src/vm.c @@ -1,5 +1,6 @@ #include "vm.h" #include "memory.h" +#include "relocatable.h" #include "run_context.h" virtual_machine vm_new(void) { @@ -7,44 +8,82 @@ virtual_machine vm_new(void) { return vm; } -computed_operands_res compute_operands(virtual_machine vm, Instruction instr) { - relocatable dst_addr = compute_dst_addr(vm.run_context, instr); - ResultMemory mem_res = memory_get(&vm.memory, dst_addr); - if (mem_res.type == Err) { - computed_operands_res res = {.value = {.error = MemoryError}, .is_error = true}; - return res; +maybe_relocatable compute_res(Instruction instr, maybe_relocatable op0, maybe_relocatable op1) { + maybe_relocatable res; + switch (instr.res) { + case Op1: + res = op1; + break; + case Res_Add: + res = add_maybe_relocatable(op0, op1); + break; + case Mul: + if (op0.is_felt && op1.is_felt) { + felt_t a = {op0.value.felt[0], op0.value.felt[1], op0.value.felt[2], op0.value.felt[3]}; + felt_t b = {op1.value.felt[0], op1.value.felt[1], op1.value.felt[2], op1.value.felt[3]}; + felt_t result; + mul(a, b, result); + res = (maybe_relocatable){.is_felt = true, + .value = {.felt = {result[0], result[1], result[2], result[3]}}}; + } + break; + default: + // TODO: in rust this is a none, we should check what to do in this cases + res = (maybe_relocatable){.is_felt = false, .value = {.relocatable = {0, 0}}}; + break; } - relocatable op0_addr = compute_op0_addr(vm.run_context, instr); - ResultMemory op0_op = memory_get(&vm.memory, op0_addr); - if (op0_op.type == Err) { - computed_operands_res res = {.value = {.error = MemoryError}, .is_error = true}; - return res; - } + computed_operands_res compute_operands(virtual_machine vm, Instruction instr) { + relocatable dst_addr = compute_dst_addr(vm.run_context, instr); + ResultMemory mem_res = memory_get(&vm.memory, dst_addr); + if (mem_res.type == Err) { + computed_operands_res res = {.value = {.error = MemoryError}, .is_error = true}; + return res; + } - relocatable op1_addr = compute_op1_addr(vm.run_context, instr, op0_op.value.memory_value); - ResultMemory op1_op = memory_get(&vm.memory, op1_addr); + relocatable op0_addr = compute_op0_addr(vm.run_context, instr); + ResultMemory op0_op = memory_get(&vm.memory, op0_addr); + if (op0_op.type == Err) { + computed_operands_res res = {.value = {.error = MemoryError}, .is_error = true}; + return res; + } - felt_t value; - from(value, 0); - maybe_relocatable res = {.is_felt = false, .value = {.felt = {value[0], value[1], value[2], value[3]}}}; - uint8_t deduced_operands = 0; -} + relocatable op1_addr = compute_op1_addr(vm.run_context, instr, op0_op.value.memory_value); + ResultMemory op1_op = memory_get(&vm.memory, op1_addr); + + felt_t value; + from(value, 0); + // maybe_relocatable res = {.is_felt = false, .value = {.felt = {value[0], value[1], value[2], + // value[3]}}}; + uint8_t deduced_operands = 0; + + if (op0_op.type == Err) { + computed_operands_res res = {.value = {.error = MemoryError}, .is_error = true}; + return res; + } + + // for now this is always pre computed. we should handle the case when it is not + maybe_relocatable op0 = op0_op.value.memory_value; + maybe_relocatable op1 = op1_op.value.memory_value; + + // compute res + maybe_relocatable res = compute_res(instr); + } -// TODO: uncomment once all functions are done -// vm_result run_instruction(virtual_machine vm, Instruction instr) { + // TODO: uncomment once all functions are done + // vm_result run_instruction(virtual_machine vm, Instruction instr) { -// computed_operands_res com_op_res = compute_operands(vm, instr); -// if (com_op_res.is_error) { -// VirtualMachineError err = com_op_res.value.error; -// vm_result res = {.is_ok = false, .error = err}; -// return res; -// } + // computed_operands_res com_op_res = compute_operands(vm, instr); + // if (com_op_res.is_error) { + // VirtualMachineError err = com_op_res.value.error; + // vm_result res = {.is_ok = false, .error = err}; + // return res; + // } -// vm_result res = { -// .is_ok = true, -// .error = None, -// }; + // vm_result res = { + // .is_ok = true, + // .error = None, + // }; -// return res; -// } + // return res; + // } diff --git a/src/vm.h b/src/vm.h index 341580c..1452444 100644 --- a/src/vm.h +++ b/src/vm.h @@ -4,6 +4,7 @@ #include "instruction.h" #include "memory.h" #include "run_context.h" +#include "relocatable.h" typedef struct { enum VirtualMachineError error; From 443d5aead65f046e4d6422df4e68635b813c1300 Mon Sep 17 00:00:00 2001 From: Milton Date: Wed, 26 Jul 2023 11:56:37 -0300 Subject: [PATCH 55/59] Add maybe relocatable --- src/utils.c | 47 +++++++++++++++++++++------ src/utils.h | 2 ++ src/vm.c | 93 ++++++++++++++++++++++++++--------------------------- src/vm.h | 5 +-- 4 files changed, 88 insertions(+), 59 deletions(-) diff --git a/src/utils.c b/src/utils.c index 2548da5..f62ee84 100644 --- a/src/utils.c +++ b/src/utils.c @@ -1,21 +1,48 @@ #include "utils.h" #include "relocatable.h" +#include +// TODO: check this function +uint64_t to_u64(felt_t f) { return f[3]; } +maybe_relocatable add_maybe_relocatable(maybe_relocatable a, maybe_relocatable b) { + if (a.is_felt && b.is_felt) { -maybe_relocatable add_maybe_relocatable(maybe_relocatable a, maybe_relocatable b){ - if(a.is_felt && b.is_felt) { - - felt_t f1 = {a.value.felt[0], a.value.felt[1], a.value.felt[2], a.value.felt[3]}; - felt_t f2 = {b.value.felt[0], b.value.felt[1], b.value.felt[2], b.value.felt[3]}; - felt_t result; - add(f1, f2, result); - maybe_relocatable res = {.is_felt = true, .value = {.felt = {result[0], result[1], result[2], result[3]}}}; + felt_t f1 = {a.value.felt[0], a.value.felt[1], a.value.felt[2], a.value.felt[3]}; + felt_t f2 = {b.value.felt[0], b.value.felt[1], b.value.felt[2], b.value.felt[3]}; + felt_t result; + add(f1, f2, result); + maybe_relocatable res = {.is_felt = true, + .value = {.felt = {result[0], result[1], result[2], result[3]}}}; + return res; + } else if (a.is_felt && !b.is_felt) { + + felt_t f1 = {a.value.felt[0], a.value.felt[1], a.value.felt[2], a.value.felt[3]}; + relocatable rel = b.value.relocatable; + uint64_t offset = (uint64_t)rel.offset; + uint64_t other = to_u64(f1); + uint64_t new_offset = offset + other; + maybe_relocatable res = { + .is_felt = false, + .value = {.relocatable = {.offset = new_offset, .segment_index = rel.segment_index}}}; + return res; + } else if (!a.is_felt && b.is_felt) { + + felt_t f1 = {a.value.felt[0], a.value.felt[1], a.value.felt[2], a.value.felt[3]}; + relocatable rel = b.value.relocatable; + uint64_t offset = (uint64_t)rel.offset; + uint64_t other = to_u64(f1); + uint64_t new_offset = offset + other; + maybe_relocatable res = { + .is_felt = false, + .value = {.relocatable = {.offset = new_offset, .segment_index = rel.segment_index}}}; return res; } -} - + felt_t res; + zero(res); + return (maybe_relocatable){.is_felt = true, .value = {.felt = {res[0], res[1], res[2], res[3]}}}; +} int64_t absolute(int64_t a) { if (a < 0) diff --git a/src/utils.h b/src/utils.h index a417637..5b27954 100644 --- a/src/utils.h +++ b/src/utils.h @@ -2,12 +2,14 @@ #define UTILS_H #include "../lambdaworks/lib/lambdaworks.h" +#include "relocatable.h" #include "stdint.h" #include "stdio.h" #include bool felt_equal(felt_t a, felt_t b); int64_t absolute(int64_t a); +maybe_relocatable add_maybe_relocatable(maybe_relocatable a, maybe_relocatable b); uint8_t *u64_to_le_bytes(uint64_t value, uint8_t *buffer_bytes); uint8_t *u64_to_be_bytes(uint64_t value, uint8_t *buffer_bytes); diff --git a/src/vm.c b/src/vm.c index c3c5b8f..707368a 100644 --- a/src/vm.c +++ b/src/vm.c @@ -1,7 +1,4 @@ #include "vm.h" -#include "memory.h" -#include "relocatable.h" -#include "run_context.h" virtual_machine vm_new(void) { virtual_machine vm = {{{0, 0}, {0, 0}, {0, 0}}, memory_new()}; @@ -32,58 +29,60 @@ maybe_relocatable compute_res(Instruction instr, maybe_relocatable op0, maybe_re res = (maybe_relocatable){.is_felt = false, .value = {.relocatable = {0, 0}}}; break; } + return res; +} - computed_operands_res compute_operands(virtual_machine vm, Instruction instr) { - relocatable dst_addr = compute_dst_addr(vm.run_context, instr); - ResultMemory mem_res = memory_get(&vm.memory, dst_addr); - if (mem_res.type == Err) { - computed_operands_res res = {.value = {.error = MemoryError}, .is_error = true}; - return res; - } +computed_operands_res compute_operands(virtual_machine vm, Instruction instr) { + relocatable dst_addr = compute_dst_addr(vm.run_context, instr); + ResultMemory mem_res = memory_get(&vm.memory, dst_addr); + if (mem_res.type == Err) { + computed_operands_res res = {.value = {.error = MemoryError}, .is_error = true}; + return res; + } - relocatable op0_addr = compute_op0_addr(vm.run_context, instr); - ResultMemory op0_op = memory_get(&vm.memory, op0_addr); - if (op0_op.type == Err) { - computed_operands_res res = {.value = {.error = MemoryError}, .is_error = true}; - return res; - } + relocatable op0_addr = compute_op0_addr(vm.run_context, instr); + ResultMemory op0_op = memory_get(&vm.memory, op0_addr); + if (op0_op.type == Err) { + computed_operands_res res = {.value = {.error = MemoryError}, .is_error = true}; + return res; + } - relocatable op1_addr = compute_op1_addr(vm.run_context, instr, op0_op.value.memory_value); - ResultMemory op1_op = memory_get(&vm.memory, op1_addr); + relocatable op1_addr = compute_op1_addr(vm.run_context, instr, op0_op.value.memory_value); + ResultMemory op1_op = memory_get(&vm.memory, op1_addr); - felt_t value; - from(value, 0); - // maybe_relocatable res = {.is_felt = false, .value = {.felt = {value[0], value[1], value[2], - // value[3]}}}; - uint8_t deduced_operands = 0; + felt_t value; + from(value, 0); + // maybe_relocatable res = {.is_felt = false, .value = {.felt = {value[0], value[1], value[2], + // value[3]}}}; + uint8_t deduced_operands = 0; - if (op0_op.type == Err) { - computed_operands_res res = {.value = {.error = MemoryError}, .is_error = true}; - return res; - } + if (op0_op.type == Err) { + computed_operands_res res = {.value = {.error = MemoryError}, .is_error = true}; + return res; + } - // for now this is always pre computed. we should handle the case when it is not - maybe_relocatable op0 = op0_op.value.memory_value; - maybe_relocatable op1 = op1_op.value.memory_value; + // for now this is always pre computed. we should handle the case when it is not + maybe_relocatable op0 = op0_op.value.memory_value; + maybe_relocatable op1 = op1_op.value.memory_value; - // compute res - maybe_relocatable res = compute_res(instr); - } + // compute res + maybe_relocatable res = compute_res(instr, op0, op1); +} - // TODO: uncomment once all functions are done - // vm_result run_instruction(virtual_machine vm, Instruction instr) { +// TODO: uncomment once all functions are done +// vm_result run_instruction(virtual_machine vm, Instruction instr) { - // computed_operands_res com_op_res = compute_operands(vm, instr); - // if (com_op_res.is_error) { - // VirtualMachineError err = com_op_res.value.error; - // vm_result res = {.is_ok = false, .error = err}; - // return res; - // } +// computed_operands_res com_op_res = compute_operands(vm, instr); +// if (com_op_res.is_error) { +// VirtualMachineError err = com_op_res.value.error; +// vm_result res = {.is_ok = false, .error = err}; +// return res; +// } - // vm_result res = { - // .is_ok = true, - // .error = None, - // }; +// vm_result res = { +// .is_ok = true, +// .error = None, +// }; - // return res; - // } +// return res; +// } diff --git a/src/vm.h b/src/vm.h index 1452444..9058d31 100644 --- a/src/vm.h +++ b/src/vm.h @@ -3,8 +3,9 @@ #include "instruction.h" #include "memory.h" -#include "run_context.h" #include "relocatable.h" +#include "run_context.h" +#include "utils.h" typedef struct { enum VirtualMachineError error; @@ -58,5 +59,5 @@ virtual_machine vm_new(void); // executes an instruction in the vm vm_result run_instruction(virtual_machine vm, Instruction instr); // Creates a new, empty virtual_machine - +maybe_relocatable compute_res(Instruction instr, maybe_relocatable op0, maybe_relocatable op1); #endif From 70486a59b202e445a055dc0e7e494e0447d4b329 Mon Sep 17 00:00:00 2001 From: Milton Date: Thu, 27 Jul 2023 10:20:10 -0300 Subject: [PATCH 56/59] Fix err typo --- src/memory.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/memory.c b/src/memory.c index 222d5a7..a4a4fd9 100644 --- a/src/memory.c +++ b/src/memory.c @@ -46,7 +46,7 @@ ResultMemory memory_insert(memory *mem, relocatable ptr, maybe_relocatable value } ResultMemory get_result = memory_get(mem, ptr); // Check for possible ovewrites - if (!get_result.type) { + if (get_result.type != Err) { if (maybe_relocatable_equal(get_result.value.memory_value, value)) { ResultMemory ok = {.type = Int, .value = {.none = 0}}; return ok; From e5227fb33d7b121080b9ce1a78b8edd1795c83c7 Mon Sep 17 00:00:00 2001 From: Milton Date: Thu, 27 Jul 2023 13:42:07 -0300 Subject: [PATCH 57/59] Fix test --- src/vm.c | 21 ++++++++++++++++++--- src/vm.h | 16 ++++++++-------- test/memory_tests.c | 34 +++++++++++++++------------------- test/memory_tests.h | 2 ++ test/runner_tests.c | 12 ++++++------ 5 files changed, 49 insertions(+), 36 deletions(-) diff --git a/src/vm.c b/src/vm.c index 707368a..0e1ba09 100644 --- a/src/vm.c +++ b/src/vm.c @@ -34,8 +34,8 @@ maybe_relocatable compute_res(Instruction instr, maybe_relocatable op0, maybe_re computed_operands_res compute_operands(virtual_machine vm, Instruction instr) { relocatable dst_addr = compute_dst_addr(vm.run_context, instr); - ResultMemory mem_res = memory_get(&vm.memory, dst_addr); - if (mem_res.type == Err) { + ResultMemory dst_op = memory_get(&vm.memory, dst_addr); + if (dst_op.type == Err) { computed_operands_res res = {.value = {.error = MemoryError}, .is_error = true}; return res; } @@ -67,8 +67,23 @@ computed_operands_res compute_operands(virtual_machine vm, Instruction instr) { // compute res maybe_relocatable res = compute_res(instr, op0, op1); -} + // compute dst + maybe_relocatable dst = dst_op.value.memory_value; + + operands_addresses accessed_addresses = { + .dst_addr = {.offset = dst_addr.offset, .segment_index = dst_addr.segment_index}, + .op0_addr = {.offset = op0_addr.offset, .segment_index = op0_addr.segment_index}, + .op1_addr = {.offset = op1_addr.offset, .segment_index = op1_addr.segment_index}, + }; + + operands operands = {.dst = dst, .op0 = op0, .op1 = op1, .res = res}; + computed_operands_res result = { + .is_error = false, + .value = {.ops = {.oprs = operands, .op_addrs = accessed_addresses, .deduced_operands = deduced_operands}}}; + + return result; +} // TODO: uncomment once all functions are done // vm_result run_instruction(virtual_machine vm, Instruction instr) { diff --git a/src/vm.h b/src/vm.h index 9058d31..0a6d414 100644 --- a/src/vm.h +++ b/src/vm.h @@ -21,31 +21,31 @@ typedef struct { // execution structures // --------------------- -typedef struct { +typedef struct operands { maybe_relocatable dst; - memory_cell res; + maybe_relocatable res; maybe_relocatable op0; maybe_relocatable op1; } operands; -typedef struct { +typedef struct operands_addresses { relocatable dst_addr; relocatable op0_addr; relocatable op1_addr; -} operands_address; +} operands_addresses; -typedef struct { +typedef struct computed_operands { operands oprs; - operands_address op_addrs; + operands_addresses op_addrs; uint8_t deduced_operands; } computed_operands; -typedef union { +typedef union computed_operands_value { computed_operands ops; VirtualMachineError error; } computed_operands_value; -typedef struct { +typedef struct computed_operands_res { computed_operands_value value; bool is_error; } computed_operands_res; diff --git a/test/memory_tests.c b/test/memory_tests.c index 0afd90e..e89de91 100644 --- a/test/memory_tests.c +++ b/test/memory_tests.c @@ -1,15 +1,11 @@ #include "memory_tests.h" -#include "relocatable.h" -#include "utils.h" -#include -#include void memory_get_err(void) { // Initialize memory memory mem = memory_new(); relocatable ptr = {0, 0}; ResultMemory result = memory_get(&mem, ptr); - assert(result.is_error); + assert(result.type == Err); assert(result.value.error == Get); memory_free(&mem); printf("OK!\n"); @@ -23,7 +19,7 @@ void memory_insert_err_unallocated_segement(void) { one(f); maybe_relocatable elem = {.is_felt = true, .value = {.felt = {f[0], f[1], f[2], f[3]}}}; ResultMemory result = memory_insert(&mem, ptr, elem); - assert(result.is_error); + assert(result.type == Err); assert(result.value.error == Insert); memory_free(&mem); printf("OK!\n"); @@ -38,12 +34,12 @@ void memory_insert_err_ovewrite_attempt(void) { one(felt_one); maybe_relocatable elem = maybe_relocatable_from_felt_limbs(felt_one); ResultMemory result = memory_insert(&mem, ptr, elem); - assert(!result.is_error); + assert(result.type != Err); felt_t felt_two; from(felt_two, 2); maybe_relocatable elem_b = maybe_relocatable_from_felt_limbs(felt_two); ResultMemory result_b = memory_insert(&mem, ptr, elem_b); - assert(result_b.is_error); + assert(result_b.type == Err); assert(result_b.value.error == Insert); memory_free(&mem); printf("OK!\n"); @@ -58,10 +54,10 @@ void memory_insert_ok_ovewrite_same_value(void) { one(felt_one); maybe_relocatable elem = maybe_relocatable_from_felt_limbs(felt_one); ResultMemory result = memory_insert(&mem, ptr, elem); - assert(!result.is_error); + assert(result.type != Err); maybe_relocatable elem_b = maybe_relocatable_from_felt_limbs(felt_one); ResultMemory result_b = memory_insert(&mem, ptr, elem_b); - assert(!result_b.is_error); + assert(result_b.type != Err); memory_free(&mem); printf("OK!\n"); } @@ -75,10 +71,10 @@ void memory_insert_ok(void) { one(felt_one); maybe_relocatable elem = maybe_relocatable_from_felt_limbs(felt_one); ResultMemory result_insert = memory_insert(&mem, ptr, elem); - assert(!result_insert.is_error); + assert(result_insert.type != Err); assert(result_insert.value.none == 0); ResultMemory result_get = memory_get(&mem, ptr); - assert(!result_get.is_error); + assert(result_get.type != Err); assert(felt_equal(result_get.value.memory_value.value.felt, felt_one)); memory_free(&mem); printf("OK!\n"); @@ -93,10 +89,10 @@ void memory_insert_with_gap(void) { one(felt_one); maybe_relocatable elem = maybe_relocatable_from_felt_limbs(felt_one); ResultMemory result_insert = memory_insert(&mem, ptr, elem); - assert(!result_insert.is_error); + assert(result_insert.type != Err); assert(result_insert.value.none == 0); ResultMemory result_get = memory_get(&mem, ptr); - assert(!result_get.is_error); + assert(result_get.type != Err); assert(felt_equal(result_get.value.memory_value.value.felt, felt_one)); memory_free(&mem); printf("OK!\n"); @@ -115,12 +111,12 @@ void memory_load_data_one_element(void) { relocatable ptr = {0, 0}; // Load data ResultMemory load_result = memory_load_data(&mem, ptr, data); - assert(!load_result.is_error); + assert(load_result.type != Err); relocatable end_ptr = load_result.value.ptr; assert(end_ptr.segment_index == 0 && end_ptr.offset == 1); // Check memory ResultMemory result = memory_get(&mem, ptr); - assert(!result.is_error); + assert(result.type != Err); assert(maybe_relocatable_equal(result.value.memory_value, elem)); memory_free(&mem); data->free(data); @@ -136,12 +132,12 @@ void memory_load_data_empty(void) { relocatable ptr = {0, 0}; // Load data ResultMemory load_result = memory_load_data(&mem, ptr, data); - assert(!load_result.is_error); + assert(load_result.type != Err); relocatable end_ptr = load_result.value.ptr; assert(end_ptr.segment_index == 0 && end_ptr.offset == 0); // Check memory ResultMemory result = memory_get(&mem, ptr); - assert(result.is_error); + assert(result.type == Err); memory_free(&mem); data->free(data); printf("OK!\n"); @@ -155,7 +151,7 @@ void memory_load_data_err_unallocated_segment(void) { relocatable ptr = {0, 0}; // Load data ResultMemory load_result = memory_load_data(&mem, ptr, data); - assert(load_result.is_error); + assert(load_result.type == Err); assert(load_result.value.error == LoadData); data->free(data); memory_free(&mem); diff --git a/test/memory_tests.h b/test/memory_tests.h index f955f15..af56dda 100644 --- a/test/memory_tests.h +++ b/test/memory_tests.h @@ -2,6 +2,8 @@ #define MEMORY_TEST_H #include "../lambdaworks/lib/lambdaworks.h" +#include "../src/relocatable.h" +#include "../src/utils.h" #include "memory.h" #include #include diff --git a/test/runner_tests.c b/test/runner_tests.c index 3a26b8b..5506fd5 100644 --- a/test/runner_tests.c +++ b/test/runner_tests.c @@ -37,18 +37,18 @@ void initialize_runner_no_builtins_no_proof_mode_non_empty_program(void) { // program segment relocatable ptr = {0, 0}; ResultMemory result = memory_get(&memory, ptr); - assert(!result.is_error); + assert(result.type != Err); assert(felt_equal(result.value.memory_value.value.felt, felt_one)); // execution segment relocatable ptr_b = {1, 0}; ResultMemory result_b = memory_get(&memory, ptr_b); - assert(!result_b.is_error); + assert(result_b.type != Err); relocatable value_b = result_b.value.memory_value.value.relocatable; assert(value_b.segment_index == 2 && value_b.offset == 0); relocatable ptr_c = {1, 1}; ResultMemory result_c = memory_get(&memory, ptr_c); - assert(!result_c.is_error); + assert(result_c.type != Err); relocatable value_c = result_c.value.memory_value.value.relocatable; assert(value_c.segment_index == 3 && value_c.offset == 0); @@ -81,17 +81,17 @@ void initialize_runner_no_builtins_no_proof_mode_empty_program(void) { assert(memory.num_segments == 4); relocatable ptr = {0, 0}; ResultMemory result = memory_get(&memory, ptr); - assert(result.is_error); + assert(result.type == Err); // execution segment relocatable ptr_b = {1, 0}; ResultMemory result_b = memory_get(&memory, ptr_b); - assert(!result_b.is_error); + assert(result_b.type != Err); relocatable value_b = result_b.value.memory_value.value.relocatable; assert(value_b.segment_index == 2 && value_b.offset == 0); relocatable ptr_c = {1, 1}; ResultMemory result_c = memory_get(&memory, ptr_c); - assert(!result_c.is_error); + assert(result_c.type != Err); relocatable value_c = result_c.value.memory_value.value.relocatable; assert(value_c.segment_index == 3 && value_c.offset == 0); runner_free(&runner); From c77aecc441ee3b8f39d25d628ceeeaae8aae45ac Mon Sep 17 00:00:00 2001 From: Milton Date: Thu, 27 Jul 2023 17:07:51 -0300 Subject: [PATCH 58/59] Fix error on mac --- src/vm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/vm.c b/src/vm.c index 0e1ba09..0a50e3b 100644 --- a/src/vm.c +++ b/src/vm.c @@ -22,6 +22,8 @@ maybe_relocatable compute_res(Instruction instr, maybe_relocatable op0, maybe_re mul(a, b, result); res = (maybe_relocatable){.is_felt = true, .value = {.felt = {result[0], result[1], result[2], result[3]}}}; + } else { + res = (maybe_relocatable){.is_felt = false, .value = {.relocatable = {0, 0}}}; } break; default: From 3c6f0734ef6107a82c8752ca121fe895e1233632 Mon Sep 17 00:00:00 2001 From: Milton Date: Fri, 28 Jul 2023 12:31:08 -0300 Subject: [PATCH 59/59] insert_deduced operatnds --- src/utils.c | 23 ++++++++++++++++++----- src/vm.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 65 insertions(+), 9 deletions(-) diff --git a/src/utils.c b/src/utils.c index f62ee84..23d8fd8 100644 --- a/src/utils.c +++ b/src/utils.c @@ -2,8 +2,21 @@ #include "relocatable.h" #include +typedef struct felt_to_u64_result { + bool is_ok; + uint64_t val; +} felt_to_u64_result; + // TODO: check this function -uint64_t to_u64(felt_t f) { return f[3]; } +felt_to_u64_result to_u64(felt_t f) { + if (f[0] == 0 && f[1] == 0 && f[2] == 0) { + felt_to_u64_result res = {.is_ok = true, .val = f[3]}; + return res; + } else { + felt_to_u64_result res = {.is_ok = false, .val = 0}; + return res; + }; +} maybe_relocatable add_maybe_relocatable(maybe_relocatable a, maybe_relocatable b) { if (a.is_felt && b.is_felt) { @@ -20,8 +33,8 @@ maybe_relocatable add_maybe_relocatable(maybe_relocatable a, maybe_relocatable b felt_t f1 = {a.value.felt[0], a.value.felt[1], a.value.felt[2], a.value.felt[3]}; relocatable rel = b.value.relocatable; uint64_t offset = (uint64_t)rel.offset; - uint64_t other = to_u64(f1); - uint64_t new_offset = offset + other; + felt_to_u64_result other = to_u64(f1); + uint64_t new_offset = offset + other.val; maybe_relocatable res = { .is_felt = false, .value = {.relocatable = {.offset = new_offset, .segment_index = rel.segment_index}}}; @@ -31,8 +44,8 @@ maybe_relocatable add_maybe_relocatable(maybe_relocatable a, maybe_relocatable b felt_t f1 = {a.value.felt[0], a.value.felt[1], a.value.felt[2], a.value.felt[3]}; relocatable rel = b.value.relocatable; uint64_t offset = (uint64_t)rel.offset; - uint64_t other = to_u64(f1); - uint64_t new_offset = offset + other; + felt_to_u64_result other = to_u64(f1); + uint64_t new_offset = offset + other.val; maybe_relocatable res = { .is_felt = false, .value = {.relocatable = {.offset = new_offset, .segment_index = rel.segment_index}}}; diff --git a/src/vm.c b/src/vm.c index 0a50e3b..858a79c 100644 --- a/src/vm.c +++ b/src/vm.c @@ -34,6 +34,50 @@ maybe_relocatable compute_res(Instruction instr, maybe_relocatable op0, maybe_re return res; } +bool was_op0_deducted(uint8_t ded_ops) { return (ded_ops & 1 << 1) != 0; } +bool was_op1_deducted(uint8_t ded_ops) { return (ded_ops & 1 << 2) != 0; } +bool was_dst_deducted(uint8_t ded_ops) { return (ded_ops & 1) != 0; } + +vm_result insert_deduced_operands(memory mem, uint8_t ded_ops, operands opers, operands_addresses oper_addr) { + vm_result result; + if (was_op0_deducted(ded_ops)) { + ResultMemory res = memory_insert(&mem, oper_addr.op0_addr, opers.op0); + if (res.type == Err) { + result = (vm_result){ + .is_ok = false, + .error = MemoryError, + }; + } + } + if (was_op1_deducted(ded_ops)) { + ResultMemory res = memory_insert(&mem, oper_addr.op1_addr, opers.op1); + if (res.type == Err) { + result = (vm_result){ + .is_ok = false, + .error = MemoryError, + }; + } + } + if (was_dst_deducted(ded_ops)) { + ResultMemory res = memory_insert(&mem, oper_addr.dst_addr, opers.dst); + if (res.type == Err) { + result = (vm_result){ + .is_ok = false, + .error = MemoryError, + }; + } + } + + else { + result = (vm_result){ + .is_ok = true, + .error = None, + }; + } + + return result; +} + computed_operands_res compute_operands(virtual_machine vm, Instruction instr) { relocatable dst_addr = compute_dst_addr(vm.run_context, instr); ResultMemory dst_op = memory_get(&vm.memory, dst_addr); @@ -44,10 +88,6 @@ computed_operands_res compute_operands(virtual_machine vm, Instruction instr) { relocatable op0_addr = compute_op0_addr(vm.run_context, instr); ResultMemory op0_op = memory_get(&vm.memory, op0_addr); - if (op0_op.type == Err) { - computed_operands_res res = {.value = {.error = MemoryError}, .is_error = true}; - return res; - } relocatable op1_addr = compute_op1_addr(vm.run_context, instr, op0_op.value.memory_value); ResultMemory op1_op = memory_get(&vm.memory, op1_addr); @@ -65,6 +105,9 @@ computed_operands_res compute_operands(virtual_machine vm, Instruction instr) { // for now this is always pre computed. we should handle the case when it is not maybe_relocatable op0 = op0_op.value.memory_value; + if (op0_op.type == Err) { + + } maybe_relocatable op1 = op1_op.value.memory_value; // compute res