aboutsummaryrefslogtreecommitdiff
path: root/pseudocode-lib
diff options
context:
space:
mode:
author_ov4 <ov4@ov4.org>2026-10-27 13:21:54 +0000
committer_ov4 <ov4@ov4.org>2026-10-27 13:21:54 +0000
commit790e0fd7c5a81b9a27a6d84e0f3f4c7a0b17d04b (patch)
tree24d0b24b6d1dbdb92e9c7bad2e5273b638f4e81a /pseudocode-lib
parent76ec25df16629b17f7d2775f4d2a54db0d022428 (diff)
refactor(memory): add tracked allocation runtime to the standard library
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'pseudocode-lib')
-rw-r--r--pseudocode-lib/memory.cc73
1 files changed, 73 insertions, 0 deletions
diff --git a/pseudocode-lib/memory.cc b/pseudocode-lib/memory.cc
new file mode 100644
index 0000000..5eed4c0
--- /dev/null
+++ b/pseudocode-lib/memory.cc
@@ -0,0 +1,73 @@
+#include <cstddef>
+#include <cstdio>
+#include <cstdlib>
+
+extern "C" int __cps_user_line;
+
+namespace {
+struct Allocation {
+ void *Address;
+ Allocation *Next;
+};
+Allocation *Head = nullptr;
+
+[[noreturn]] void fail(const char *Reason) {
+ std::fprintf(stderr, "[Fatal] line %d: %s\n", __cps_user_line, Reason);
+ throw 0;
+}
+
+// Return the link owning the node so head and interior removals are identical.
+Allocation **find(void *Address) {
+ for (Allocation **Link = &Head; *Link; Link = &(*Link)->Next)
+ if ((*Link)->Address == Address) return Link;
+ fail("Invalid memory address (not an active allocation)");
+}
+}
+
+extern "C" {
+void *_memory_impl_malloc(unsigned long long Bytes) {
+ std::size_t Size = static_cast<std::size_t>(Bytes);
+ if (!Size) return nullptr;
+ auto *Node = static_cast<Allocation *>(std::malloc(sizeof(Allocation)));
+ if (!Node) fail("Allocation tracking failed");
+ void *Address = std::malloc(Size);
+ if (!Address) {
+ std::free(Node);
+ fail("Memory allocation failed");
+ }
+ Node->Address = Address;
+ Node->Next = Head;
+ Head = Node;
+ return Address;
+}
+
+void _memory_impl_validate(void *Address) {
+ find(Address);
+}
+
+void *_memory_impl_free(void *Address) {
+ if (Address) {
+ Allocation **Link = find(Address);
+ Allocation *Node = *Link;
+ *Link = Node->Next;
+ std::free(Address);
+ std::free(Node);
+ }
+ return Address;
+}
+
+void *_memory_impl_realloc(void *Address, unsigned long long Bytes) {
+ std::size_t Size = static_cast<std::size_t>(Bytes);
+ if (!Address) return _memory_impl_malloc(Bytes);
+ Allocation *Node = *find(Address);
+ if (!Size) {
+ _memory_impl_free(Address);
+ return nullptr;
+ }
+ void *Resized = std::realloc(Address, Size);
+ // Failure preserves both the original allocation and its tracking record.
+ if (!Resized) fail("Memory allocation failed");
+ Node->Address = Resized;
+ return Resized;
+}
+}