From f9117a23532564f252437f6502a887ba048ed463 Mon Sep 17 00:00:00 2001 From: Ed_ Date: Wed, 23 Aug 2023 11:05:49 -0400 Subject: [PATCH] Added zpl's ivrtual memory to dependencies (unused for now) --- gencpp.10x | 1 + project/components/ast.cpp | 3 + project/components/ast.hpp | 6 +- project/components/ast_types.hpp | 3 +- project/components/interface.parsing.cpp | 10 ++ project/dependencies/memory.cpp | 126 +++++++++++++++++++++++ project/dependencies/memory.hpp | 27 +++++ 7 files changed, 173 insertions(+), 3 deletions(-) diff --git a/gencpp.10x b/gencpp.10x index 8cb3c94..c8d06e3 100644 --- a/gencpp.10x +++ b/gencpp.10x @@ -40,6 +40,7 @@ GEN_TIME + GEN_SYSTEM_WINDOWS diff --git a/project/components/ast.cpp b/project/components/ast.cpp index 86055e4..2fb0ff3 100644 --- a/project/components/ast.cpp +++ b/project/components/ast.cpp @@ -779,6 +779,9 @@ String AST::to_string() { result.append_fmt( "%S", Name ); } + + if ( IsParamPack ) + result.append("..."); } break; diff --git a/project/components/ast.hpp b/project/components/ast.hpp index 07f669a..96040ca 100644 --- a/project/components/ast.hpp +++ b/project/components/ast.hpp @@ -264,7 +264,8 @@ struct AST CodeT Type; ModuleFlag ModuleFlags; union { - b32 IsFunction; // Used by typedef to not serialize the name field. + b32 IsFunction; // Used by typedef to not serialize the name field. + b32 IsParamPack; // Used by typename to know if type should be considered a parameter pack. OperatorT Op; AccessSpec ParentAccess; s32 NumEntries; @@ -314,7 +315,8 @@ struct AST_POD CodeT Type; ModuleFlag ModuleFlags; union { - b32 IsFunction; // Used by typedef to not serialize the name field. + b32 IsFunction; // Used by typedef to not serialize the name field. + b32 IsParamPack; // Used by typename to know if type should be considered a parameter pack. OperatorT Op; AccessSpec ParentAccess; s32 NumEntries; diff --git a/project/components/ast_types.hpp b/project/components/ast_types.hpp index 15710e2..00ec5ad 100644 --- a/project/components/ast_types.hpp +++ b/project/components/ast_types.hpp @@ -459,7 +459,8 @@ struct AST_Type Code Parent; StringCached Name; CodeT Type; - char _PAD_UNUSED_[ sizeof(ModuleFlag) + sizeof(u32) ]; + char _PAD_UNUSED_[ sizeof(ModuleFlag) ]; + b32 IsParamPack; }; static_assert( sizeof(AST_Type) == sizeof(AST), "ERROR: AST_Type is not the same size as AST"); diff --git a/project/components/interface.parsing.cpp b/project/components/interface.parsing.cpp index caf14dd..c65ef79 100644 --- a/project/components/interface.parsing.cpp +++ b/project/components/interface.parsing.cpp @@ -4454,6 +4454,13 @@ CodeType parse_type( bool* is_function ) brute_sig.Length = ( (sptr)prevtok.Text + prevtok.Length ) - (sptr)brute_sig.Text; is_first_capture = false; } + + bool is_param_pack = false; + if ( check(TokType::Varadic_Argument) ) + { + is_param_pack = true; + eat( TokType::Varadic_Argument ); + } using namespace ECode; @@ -4479,6 +4486,9 @@ CodeType parse_type( bool* is_function ) if ( attributes ) result->Attributes = attributes; + + if ( is_param_pack ) + result->IsParamPack = true; Context.pop(); return result; diff --git a/project/dependencies/memory.cpp b/project/dependencies/memory.cpp index 9d7a17c..e9bdc53 100644 --- a/project/dependencies/memory.cpp +++ b/project/dependencies/memory.cpp @@ -206,6 +206,132 @@ void* heap_allocator_proc( void* allocator_data, AllocType type, sw size, sw ali return ptr; } +#pragma region VirtualMemory +VirtualMemory vm_from_memory( void* data, sw size ) +{ + VirtualMemory vm; + vm.data = data; + vm.size = size; + return vm; +} + +#if defined( GEN_SYSTEM_WINDOWS ) +VirtualMemory vm_alloc( void* addr, sw size ) +{ + VirtualMemory vm; + GEN_ASSERT( size > 0 ); + vm.data = VirtualAlloc( addr, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE ); + vm.size = size; + return vm; +} + +b32 vm_free( VirtualMemory vm ) +{ + MEMORY_BASIC_INFORMATION info; + while ( vm.size > 0 ) + { + if ( VirtualQuery( vm.data, &info, size_of( info ) ) == 0 ) + return false; + if ( info.BaseAddress != vm.data || info.AllocationBase != vm.data || info.State != MEM_COMMIT || info.RegionSize > zpl_cast( uw ) vm.size ) + { + return false; + } + if ( VirtualFree( vm.data, 0, MEM_RELEASE ) == 0 ) + return false; + vm.data = pointer_add( vm.data, info.RegionSize ); + vm.size -= info.RegionSize; + } + return true; +} + +VirtualMemory vm_trim( VirtualMemory vm, sw lead_size, sw size ) +{ + VirtualMemory new_vm = { 0 }; + void* ptr; + GEN_ASSERT( vm.size >= lead_size + size ); + + ptr = pointer_add( vm.data, lead_size ); + + vm_free( vm ); + new_vm = vm_alloc( ptr, size ); + if ( new_vm.data == ptr ) + return new_vm; + if ( new_vm.data ) + vm_free( new_vm ); + return new_vm; +} + +b32 vm_purge( VirtualMemory vm ) +{ + VirtualAlloc( vm.data, vm.size, MEM_RESET, PAGE_READWRITE ); + // NOTE: Can this really fail? + return true; +} + +sw virtual_memory_page_size( sw* alignment_out ) +{ + SYSTEM_INFO info; + GetSystemInfo( &info ); + if ( alignment_out ) + *alignment_out = info.dwAllocationGranularity; + return info.dwPageSize; +} + +#else +# include + +# ifndef MAP_ANONYMOUS +# define MAP_ANONYMOUS MAP_ANON +# endif +VirtualMemory vm_alloc( void* addr, sw size ) +{ + VirtualMemory vm; + GEN_ASSERT( size > 0 ); + vm.data = mmap( addr, size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0 ); + vm.size = size; + return vm; +} + +b32 vm_free( VirtualMemory vm ) +{ + munmap( vm.data, vm.size ); + return true; +} + +VirtualMemory vm_trim( VirtualMemory vm, sw lead_size, sw size ) +{ + void* ptr; + sw trail_size; + GEN_ASSERT( vm.size >= lead_size + size ); + + ptr = pointer_add( vm.data, lead_size ); + trail_size = vm.size - lead_size - size; + + if ( lead_size != 0 ) + vm_free( vm_from_memory(( vm.data, lead_size ) ); + if ( trail_size != 0 ) + vm_free( vm_from_memory( ptr, trail_size ) ); + return vm_from_memory( ptr, size ); +} + +b32 vm_purge( VirtualMemory vm ) +{ + int err = madvise( vm.data, vm.size, MADV_DONTNEED ); + return err != 0; +} + +sw virtual_memory_page_size( sw* alignment_out ) +{ + // TODO: Is this always true? + sw result = zpl_cast( sw ) sysconf( _SC_PAGE_SIZE ); + if ( alignment_out ) + *alignment_out = result; + return result; +} +#endif + +#pragma endregion VirtualMemory + void* Arena::allocator_proc( void* allocator_data, AllocType type, sw size, sw alignment, void* old_memory, sw old_size, u64 flags ) { Arena* arena = rcast(Arena*, allocator_data); diff --git a/project/dependencies/memory.hpp b/project/dependencies/memory.hpp index d8335db..f87b68a 100644 --- a/project/dependencies/memory.hpp +++ b/project/dependencies/memory.hpp @@ -363,6 +363,33 @@ GEN_IMPL_INLINE void zero_size( void* ptr, sw size ) mem_set( ptr, 0, size ); } +struct VirtualMemory +{ + void* data; + sw size; +}; + +//! Initialize virtual memory from existing data. +VirtualMemory vm_from_memory( void* data, sw size ); + +//! Allocate virtual memory at address with size. + +//! @param addr The starting address of the region to reserve. If NULL, it lets operating system to decide where to allocate it. +//! @param size The size to serve. +VirtualMemory vm_alloc( void* addr, sw size ); + +//! Release the virtual memory. +b32 vm_free( VirtualMemory vm ); + +//! Trim virtual memory. +VirtualMemory vm_trim( VirtualMemory vm, sw lead_size, sw size ); + +//! Purge virtual memory. +b32 gen_vm_purge( VirtualMemory vm ); + +//! Retrieve VM's page size and alignment. +sw gen_virtual_memory_page_size( sw* alignment_out ); + struct Arena { static