// Start the heap at 1024. In practice this could probably be as low as we want. // TODO: The compiler should set this global to whatever it has calculated the heap // start to be. But well, 1024 ought to be enough for now. lol. global HEAD_PTR: I32 = 1024_I32; // Every struct has a header of an I32 as a refcount. // Allocate a new item. We do not deallocate anything yet. // lol. function allocateItem(objSize: I32, align: I32): I32 = ( if align < 4_I32 then std.abort("invalid alignment"); // Include the refcount header. let actualSize = 4_I32 + objSize; // Let's see whether we can fit the refcount into the align bits. // I happen to know that everything will always be at least 4 bytes aligned. let alignedPtr = std.alignUp(HEAD_PTR, align); let actualObjPtr = if (alignedPtr - HEAD_PTR) > align then ( alignedPtr - 4_I32 ) else ( // Take up the next spot. alignedPtr + align - 4_I32 ); let newHeadPtr = actualObjPtr + actualSize; if newHeadPtr > __memory_size() then ( // 16 pages, very arbitrary. let result = __memory_grow(16_I32); // If allocation failed we get -1. We don't have negative numbers yet, lol. if result > 4294967295_I32 then ( std.abort("failed to grow memory"); ); ); HEAD_PTR = newHeadPtr; actualObjPtr ); function deallocateItem(ptr: I32, objSize: I32) = ( std.println("uwu deawwocate :3"); ); // Port of https://github.com/CCareaga/heap_allocator // // MIT License // // Copyright (c) 2017 Chris Careaga // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. global HEAP_START: HeapPtr = 2048_I32; // heap size = start+end+bin_t*BIN_COUNT // 4+ 4+ 4* 9 = 8+36=42 (round to 64) global HEAP_REGION_START: I32 = 2112_I32; // typedef struct node_t { // uint hole; // uint size; // struct node_t* next; // struct node_t* prev; // } node_t; global NODE_HOLE: I32 = 0_I32; global NODE_SIZE: I32 = 4_I32; global NODE_NEXT: I32 = 8_I32; global NODE_PREV: I32 = 12_I32; // typedef struct { // node_t *header; // } footer_t; // typedef struct { // node_t* head; // } bin_t; global SIZEOF_NODE: I32 = 16_I32; global SIZEOF_FOOTER: I32 = 4_I32; type HeapPtr = I32; type NodePtr = I32; type FootPtr = I32; type BinPtr = I32; function initHeap() = ( let heap_init_size = 65536_I32 - HEAP_REGION_START; __i32_store(HEAP_REGION_START + NODE_HOLE, 1_I32); // START.hole = __i32_store(HEAP_REGION_START + NODE_SIZE, heap_init_size - SIZEOF_NODE - SIZEOF_FOOTER); // START.size = createFoot(HEAP_REGION_START); ); function createFoot(head_node: NodePtr) = ( let foot = getFoot(head_node); __i32_store(foot, head_node); // foot.header = head_node ); function getFoot(node: NodePtr): FootPtr = ( let node_size = __i32_load(node + NODE_SIZE); node + SIZEOF_NODE + node_size ); function getWilderness() =; // llist.c function addNode(bin: BinPtr, node: NodePtr) = ( __i32_store(node + NODE_NEXT, 0_I32); // node.next = __i32_store(node + NODE_PREV, 0_I32); // node.prev = let bin_head: NodePtr = __i32_load(bin); // bin.head if (bin_head == 0_I32) then __i32_store(bin, node) // bin.head = else ( let current: NodePtr = bin_head; let previous: NodePtr = 0_I32; loop ( if (current != 0_I32) & (__i32_load(current + NODE_SIZE) // current.size <= __i32_load(node + NODE_SIZE)) // node.size then break; previous = current; current = __i32_load(current + NODE_NEXT); // current.next ); if (current == 0_I32) then ( __i32_store(previous + NODE_NEXT, node); // previous.next __i32_store(node + NODE_PREV, previous); // node.prev ) else ( if (previous != 0_I32) then ( __i32_store(node + NODE_NEXT, current); // node.next __i32_store(previous + NODE_NEXT, node); // previous.next __i32_store(node + NODE_PREV, previous); // node.prev __i32_store(current + NODE_PREV, node); // current.prev ) else ( __i32_store(node + NODE_NEXT, __i32_load(bin)); // node.next = bin.head __i32_store(__i32_load(bin) + NODE_PREV, node); // bin.head.prev = node; __i32_store(bin, node); // bin.head ); ); ) ); function removeNode(bin: BinPtr, node: NodePtr) = ( ); function test() =;