Removing heap allocations, Porting to Unix
This commit is contained in:
@@ -6,9 +6,7 @@ The language is currently **very debuggable**. It can produce readable C code wi
|
|||||||
|
|
||||||
## Using Windows API example
|
## Using Windows API example
|
||||||
|
|
||||||
* More examples can be found in /examples and /modules, especially checkout:
|
More examples can be found in /examples and /modules:
|
||||||
* examples/raymarcher.core
|
|
||||||
* examples/drawing_to_screen_using_windows_api.core
|
|
||||||
|
|
||||||
``` odin
|
``` odin
|
||||||
#import "KERNEL32.core"
|
#import "KERNEL32.core"
|
||||||
|
|||||||
280
base.cpp
280
base.cpp
@@ -1,7 +1,79 @@
|
|||||||
|
|
||||||
|
#if defined(__clang__)
|
||||||
|
# define COMPILER_CLANG 1
|
||||||
|
# if defined(_WIN32)
|
||||||
|
# define OS_WINDOWS 1
|
||||||
|
# elif defined(__linux__)
|
||||||
|
# define OS_LINUX 1
|
||||||
|
# else
|
||||||
|
# error Couldnt figure out the platform automatically
|
||||||
|
# endif
|
||||||
|
#elif defined(_MSC_VER)
|
||||||
|
# define COMPILER_MSVC 1
|
||||||
|
# define OS_WINDOWS 1
|
||||||
|
#elif defined(__GNUC__)
|
||||||
|
# define COMPILER_GCC 1
|
||||||
|
# if defined(__linux__)
|
||||||
|
# define OS_LINUX 1
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
# error Couldnt figure out the compiler
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(OS_MAC)
|
||||||
|
#define OS_UNIX 1
|
||||||
|
#endif
|
||||||
|
#if defined(OS_LINUX)
|
||||||
|
#define OS_UNIX 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(COMPILER_MSVC)
|
||||||
|
# define COMPILER_MSVC 0
|
||||||
|
#endif
|
||||||
|
#if !defined(COMPILER_GCC)
|
||||||
|
# define COMPILER_GCC 0
|
||||||
|
#endif
|
||||||
|
#if !defined(COMPILER_CLANG)
|
||||||
|
# define COMPILER_CLANG 0
|
||||||
|
#endif
|
||||||
|
#if !defined(OS_WINDOWS)
|
||||||
|
# define OS_WINDOWS 0
|
||||||
|
#endif
|
||||||
|
#if !defined(OS_LINUX)
|
||||||
|
# define OS_LINUX 0
|
||||||
|
#endif
|
||||||
|
#if !defined(OS_MAC)
|
||||||
|
# define OS_MAC 0
|
||||||
|
#endif
|
||||||
|
#if !defined(OS_UNIX)
|
||||||
|
# define OS_UNIX 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if OS_WINDOWS
|
||||||
|
#define OS_NAME "Win32"_s
|
||||||
|
#define OS_NAME_LOWER "win32"_s
|
||||||
|
#elif OS_LINUX
|
||||||
|
#define OS_NAME "Linux"_s
|
||||||
|
#define OS_NAME_LOWER "linux"_s
|
||||||
|
#elif OS_MAC
|
||||||
|
#define OS_NAME "Mac"_s
|
||||||
|
#define OS_NAME_LOWER "mac"_s
|
||||||
|
#else
|
||||||
|
#error Couldnt figure out the OS with C macros!
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if OS_WINDOWS
|
||||||
#define NOMINMAX
|
#define NOMINMAX
|
||||||
#define _CRT_SECURE_NO_WARNINGS
|
#define _CRT_SECURE_NO_WARNINGS
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
#define Breakpoint __debugbreak()
|
||||||
|
#define force_inline __forceinline
|
||||||
|
#else
|
||||||
|
#define Breakpoint (*(volatile int *)0 = 0)
|
||||||
|
#define force_inline inline
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
#include <float.h>
|
#include <float.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
typedef int8_t S8;
|
typedef int8_t S8;
|
||||||
@@ -16,12 +88,10 @@ typedef S8 B8;
|
|||||||
typedef S16 B16;
|
typedef S16 B16;
|
||||||
typedef S32 B32;
|
typedef S32 B32;
|
||||||
typedef S64 B64;
|
typedef S64 B64;
|
||||||
typedef U64 SizeU;
|
|
||||||
typedef S64 SizeS;
|
|
||||||
typedef float F32;
|
typedef float F32;
|
||||||
typedef double F64;
|
typedef double F64;
|
||||||
|
|
||||||
|
|
||||||
#define U64MAX UINT64_MAX
|
#define U64MAX UINT64_MAX
|
||||||
#define U32MAX UINT32_MAX
|
#define U32MAX UINT32_MAX
|
||||||
#define U16MAX UINT16_MAX
|
#define U16MAX UINT16_MAX
|
||||||
@@ -46,13 +116,12 @@ typedef double F64;
|
|||||||
#define api
|
#define api
|
||||||
#define function static
|
#define function static
|
||||||
#define global static
|
#define global static
|
||||||
#define force_inline __forceinline
|
#define assert(x) do{if(!(x))Breakpoint;}while(0)
|
||||||
#define assert(x) do{if(!(x))__debugbreak();}while(0)
|
#define assert_message(x,...) assert(x)
|
||||||
#define assert_msg(x,...) assert(x)
|
#define invalid_codepath assert_message(0, "Invalid codepath")
|
||||||
#define invalid_codepath assert_msg(0, "Invalid codepath")
|
#define invalid_return do{assert_message(0, "Invalid codepath"); return {};}while(0)
|
||||||
#define invalid_return do{assert_msg(0, "Invalid codepath"); return {};}while(0)
|
|
||||||
#define invalid_default_case default: invalid_codepath
|
#define invalid_default_case default: invalid_codepath
|
||||||
#define not_implemented assert_msg(0, "Not implemented")
|
#define not_implemented assert_message(0, "Not implemented")
|
||||||
#define unused(x) ((void)x)
|
#define unused(x) ((void)x)
|
||||||
#define buff_cap(x) (sizeof(x)/sizeof((x)[0]))
|
#define buff_cap(x) (sizeof(x)/sizeof((x)[0]))
|
||||||
#define is_flag_set(val,flag) ((val) & (flag))
|
#define is_flag_set(val,flag) ((val) & (flag))
|
||||||
@@ -66,59 +135,6 @@ typedef double F64;
|
|||||||
#define JOIN(X,Y) JOIN1(X,Y)
|
#define JOIN(X,Y) JOIN1(X,Y)
|
||||||
#define string_expand(x) (int)x.len, x.str
|
#define string_expand(x) (int)x.len, x.str
|
||||||
|
|
||||||
#if defined(__clang__)
|
|
||||||
# define COMPILER_CLANG 1
|
|
||||||
# if defined(_WIN32)
|
|
||||||
# define OS_WINDOWS 1
|
|
||||||
# elif defined(__linux__)
|
|
||||||
# define OS_LINUX 1
|
|
||||||
# else
|
|
||||||
# error Couldnt figure out the platform automatically
|
|
||||||
# endif
|
|
||||||
#elif defined(_MSC_VER)
|
|
||||||
# define COMPILER_MSVC 1
|
|
||||||
# define OS_WINDOWS 1
|
|
||||||
#elif defined(__GNUC__)
|
|
||||||
# define COMPILER_GCC 1
|
|
||||||
# if defined(__linux__)
|
|
||||||
# define OS_LINUX 1
|
|
||||||
# endif
|
|
||||||
#else
|
|
||||||
# error Couldnt figure out the compiler
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(COMPILER_MSVC)
|
|
||||||
# define COMPILER_MSVC 0
|
|
||||||
#endif
|
|
||||||
#if !defined(COMPILER_GCC)
|
|
||||||
# define COMPILER_GCC 0
|
|
||||||
#endif
|
|
||||||
#if !defined(COMPILER_CLANG)
|
|
||||||
# define COMPILER_CLANG 0
|
|
||||||
#endif
|
|
||||||
#if !defined(OS_WINDOWS)
|
|
||||||
# define OS_WINDOWS 0
|
|
||||||
#endif
|
|
||||||
#if !defined(OS_LINUX)
|
|
||||||
# define OS_LINUX 0
|
|
||||||
#endif
|
|
||||||
#if !defined(OS_MAC)
|
|
||||||
# define OS_MAC 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if OS_WINDOWS
|
|
||||||
#define OS_NAME "Win32"_s
|
|
||||||
#define OS_NAME_LOWER "win32"_s
|
|
||||||
#elif OS_LINUX
|
|
||||||
#define OS_NAME "Linux"_s
|
|
||||||
#define OS_NAME_LOWER "linux"_s
|
|
||||||
#elif OS_MAC
|
|
||||||
#define OS_NAME "Mac"_s
|
|
||||||
#define OS_NAME_LOWER "mac"_s
|
|
||||||
#else
|
|
||||||
#error Couldnt figure out the OS with C macros!
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct String{
|
struct String{
|
||||||
U8 *str;
|
U8 *str;
|
||||||
S64 len;
|
S64 len;
|
||||||
@@ -210,42 +226,42 @@ union Rect2I {
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Utilities
|
// Utilities
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
function SizeU
|
function size_t
|
||||||
get_align_offset(SizeU size, SizeU align){
|
get_align_offset(size_t size, size_t align){
|
||||||
SizeU mask = align - 1;
|
size_t mask = align - 1;
|
||||||
SizeU val = size & mask;
|
size_t val = size & mask;
|
||||||
if(val){
|
if(val){
|
||||||
val = align - val;
|
val = align - val;
|
||||||
}
|
}
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
function SizeU
|
function size_t
|
||||||
align_up(SizeU size, SizeU align){
|
align_up(size_t size, size_t align){
|
||||||
SizeU result = size + get_align_offset(size, align);
|
size_t result = size + get_align_offset(size, align);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function SizeU
|
function size_t
|
||||||
align_down(SizeU size, SizeU align){
|
align_down(size_t size, size_t align){
|
||||||
size += 1; // Make sure 8 when align is 8 doesn't get rounded down to 0
|
size += 1; // Make sure 8 when align is 8 doesn't get rounded down to 0
|
||||||
SizeU result = size - (align - get_align_offset(size, align));
|
size_t result = size - (align - get_align_offset(size, align));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function void
|
function void
|
||||||
memory_copy(void *dst, void *src, SizeU size){
|
memory_copy(void *dst, void *src, size_t size){
|
||||||
U8 *d = (U8*)dst;
|
U8 *d = (U8*)dst;
|
||||||
U8 *s = (U8*)src;
|
U8 *s = (U8*)src;
|
||||||
for(SizeU i = 0; i < size; i++){
|
for(size_t i = 0; i < size; i++){
|
||||||
d[i] = s[i];
|
d[i] = s[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function void
|
function void
|
||||||
memory_zero(void *p, SizeU size){
|
memory_zero(void *p, size_t size){
|
||||||
U8 *pp = (U8 *)p;
|
U8 *pp = (U8 *)p;
|
||||||
for(SizeU i = 0; i < size; i++)
|
for(size_t i = 0; i < size; i++)
|
||||||
pp[i] = 0;
|
pp[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -480,47 +496,47 @@ enum Alloc_Flag{
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct Allocator;
|
struct Allocator;
|
||||||
typedef void *Allocator_Proc(Allocator*, Allocation_Kind, void *, SizeU);
|
typedef void *Allocator_Proc(Allocator*, Allocation_Kind, void *, size_t);
|
||||||
struct Allocator{Allocator_Kind kind; Allocator_Proc *proc; String debug_name;};
|
struct Allocator{Allocator_Kind kind; Allocator_Proc *proc; String debug_name;};
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Memory OS
|
// Memory OS
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
struct OS_Memory{
|
struct OS_Memory{
|
||||||
SizeU commit, reserve;
|
size_t commit, reserve;
|
||||||
U8 *data;
|
U8 *data;
|
||||||
};
|
};
|
||||||
function OS_Memory os_reserve(SizeU size);
|
function OS_Memory os_reserve(size_t size);
|
||||||
function B32 os_commit(OS_Memory *m, SizeU size);
|
function B32 os_commit(OS_Memory *m, size_t size);
|
||||||
function void os_release(OS_Memory *m);
|
function void os_release(OS_Memory *m);
|
||||||
function B32 os_decommit_pos(OS_Memory *m, SizeU pos);
|
function B32 os_decommit_pos(OS_Memory *m, size_t pos);
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Memory arenas
|
// Memory arenas
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
global const SizeU default_reserve_size = gib(4);
|
global const size_t default_reserve_size = gib(4);
|
||||||
global const SizeU default_alignment = 8;
|
global const size_t default_alignment = 8;
|
||||||
global const SizeU additional_commit_size = mib(1);
|
global const size_t additional_commit_size = mib(1);
|
||||||
struct Arena:Allocator{
|
struct Arena:Allocator{
|
||||||
OS_Memory memory;
|
OS_Memory memory;
|
||||||
SizeU alignment;
|
size_t alignment;
|
||||||
SizeU len;
|
size_t len;
|
||||||
|
|
||||||
// Personal arena memes so we can compute correct size when resizing
|
// Personal arena memes so we can compute correct size when resizing
|
||||||
// Also a pointer so that we can make sure it didn't change
|
// Also a pointer so that we can make sure it didn't change
|
||||||
SizeU old_size;
|
size_t old_size;
|
||||||
void *debug_prev_pointer;
|
void *debug_prev_pointer;
|
||||||
};
|
};
|
||||||
function void arena_init(Arena *arena, String debug_name);
|
function void arena_init(Arena *arena, String debug_name);
|
||||||
|
|
||||||
function void
|
function void
|
||||||
arena_pop_pos(Arena *arena, SizeU pos){
|
arena_pop_pos(Arena *arena, size_t pos){
|
||||||
pos = clamp_top(pos, arena->len);
|
pos = clamp_top(pos, arena->len);
|
||||||
arena->len = pos;
|
arena->len = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
function void *
|
function void *
|
||||||
arena_pop(Arena *arena, SizeU size){
|
arena_pop(Arena *arena, size_t size){
|
||||||
size = clamp_top(size, arena->len);
|
size = clamp_top(size, arena->len);
|
||||||
arena->len -= size;
|
arena->len -= size;
|
||||||
return arena->memory.data + arena->len;
|
return arena->memory.data + arena->len;
|
||||||
@@ -537,8 +553,8 @@ arena_clear(Arena *arena){
|
|||||||
}
|
}
|
||||||
|
|
||||||
function void *
|
function void *
|
||||||
arena_push_size(Arena *a, SizeU size){
|
arena_push_size(Arena *a, size_t size){
|
||||||
SizeU generous_size = size + a->alignment;
|
size_t generous_size = size + a->alignment;
|
||||||
if(a->len+generous_size>a->memory.commit){
|
if(a->len+generous_size>a->memory.commit){
|
||||||
if(a->memory.reserve == 0){
|
if(a->memory.reserve == 0){
|
||||||
arena_init(a, "Zero initialized arena"_s);
|
arena_init(a, "Zero initialized arena"_s);
|
||||||
@@ -555,7 +571,7 @@ arena_push_size(Arena *a, SizeU size){
|
|||||||
}
|
}
|
||||||
|
|
||||||
force_inline void *
|
force_inline void *
|
||||||
arena_allocator_proc(Allocator *a, Allocation_Kind kind, void *old_pointer, SizeU size){
|
arena_allocator_proc(Allocator *a, Allocation_Kind kind, void *old_pointer, size_t size){
|
||||||
Arena *arena = (Arena *)a;
|
Arena *arena = (Arena *)a;
|
||||||
switch(kind){
|
switch(kind){
|
||||||
case Allocation_Alloc: return arena_push_size(arena, size);
|
case Allocation_Alloc: return arena_push_size(arena, size);
|
||||||
@@ -573,7 +589,7 @@ arena_allocator_proc(Allocator *a, Allocation_Kind kind, void *old_pointer, Size
|
|||||||
}
|
}
|
||||||
|
|
||||||
force_inline void *
|
force_inline void *
|
||||||
personal_arena_allocator_proc(Allocator *a, Allocation_Kind kind, void *old_pointer, SizeU size){
|
personal_arena_allocator_proc(Allocator *a, Allocation_Kind kind, void *old_pointer, size_t size){
|
||||||
Arena *arena = (Arena *)a;
|
Arena *arena = (Arena *)a;
|
||||||
arena->alignment = 1;
|
arena->alignment = 1;
|
||||||
|
|
||||||
@@ -614,59 +630,6 @@ arena_make_personal(String debug_name){
|
|||||||
return arena;
|
return arena;
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// OS Heap allocator
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
struct OS_Heap:Allocator{
|
|
||||||
HANDLE handle;
|
|
||||||
};
|
|
||||||
|
|
||||||
function void *
|
|
||||||
os_heap_allocator_proc(Allocator *a, Allocation_Kind kind, void *old_pointer, SizeU size){
|
|
||||||
OS_Heap *heap = (OS_Heap *)a;
|
|
||||||
switch(kind){
|
|
||||||
case Allocation_FreeAll:{
|
|
||||||
invalid_codepath;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
case Allocation_Destroy:{
|
|
||||||
BOOL result = HeapDestroy(heap->handle);
|
|
||||||
assert(result != 0);
|
|
||||||
heap->handle = 0;
|
|
||||||
heap->proc = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
case Allocation_Free:{
|
|
||||||
BOOL result = HeapFree(heap->handle, 0, old_pointer);
|
|
||||||
assert(result != 0);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
case Allocation_Alloc:{
|
|
||||||
void *result = HeapAlloc(heap->handle, 0, size);
|
|
||||||
assert(result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
case Allocation_Resize:{
|
|
||||||
void *result = HeapReAlloc(heap->handle, 0, old_pointer, size);
|
|
||||||
assert(result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
default: invalid_codepath;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
function OS_Heap // max_size == 0 == growing heap
|
|
||||||
win32_os_heap_create(B32 multithreaded, SizeU initial_size, SizeU max_size, String debug_name){
|
|
||||||
OS_Heap result = {};
|
|
||||||
result.debug_name = debug_name;
|
|
||||||
result.proc = os_heap_allocator_proc;
|
|
||||||
result.kind = Allocator_OSHeap;
|
|
||||||
result.handle = HeapCreate(multithreaded ? 0 : HEAP_NO_SERIALIZE, initial_size, max_size);
|
|
||||||
assert(result.handle);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum Log_Kind{Log_Kind_Normal, Log_Kind_Error, Log_Kind_Trace};
|
enum Log_Kind{Log_Kind_Normal, Log_Kind_Error, Log_Kind_Trace};
|
||||||
typedef void Log_Proc(Log_Kind kind, String string, char *file, int line);
|
typedef void Log_Proc(Log_Kind kind, String string, char *file, int line);
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@@ -684,7 +647,6 @@ struct Thread_Ctx{
|
|||||||
|
|
||||||
thread_local Thread_Ctx thread_ctx;
|
thread_local Thread_Ctx thread_ctx;
|
||||||
global Arena pernament_arena;
|
global Arena pernament_arena;
|
||||||
global OS_Heap os_process_heap;
|
|
||||||
|
|
||||||
#define REPORT_ALLOCATIONS 0
|
#define REPORT_ALLOCATIONS 0
|
||||||
#define report_file_and_line() report__file_and_line(__FILE__, __LINE__)
|
#define report_file_and_line() report__file_and_line(__FILE__, __LINE__)
|
||||||
@@ -698,7 +660,7 @@ report__file_and_line(const char *file, int line){
|
|||||||
// Implicit scratch stack
|
// Implicit scratch stack
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
struct Scratch{
|
struct Scratch{
|
||||||
SizeU saved_pos;
|
size_t saved_pos;
|
||||||
Arena *arena;
|
Arena *arena;
|
||||||
|
|
||||||
Scratch(Allocator *conflict = 0){
|
Scratch(Allocator *conflict = 0){
|
||||||
@@ -749,7 +711,7 @@ struct Scoped_Allocator{
|
|||||||
#define exp_destroy(a) (report_file_and_line(), exp__destroy(a))
|
#define exp_destroy(a) (report_file_and_line(), exp__destroy(a))
|
||||||
|
|
||||||
force_inline void *
|
force_inline void *
|
||||||
exp__alloc(Allocator *a, SizeU size, Alloc_Flag flag = AF_None){
|
exp__alloc(Allocator *a, size_t size, Alloc_Flag flag = AF_None){
|
||||||
#if REPORT_ALLOCATIONS
|
#if REPORT_ALLOCATIONS
|
||||||
printf("Alloc(%s) %s:%d %u\n", a->debug_name.str, thread_ctx.file, thread_ctx.line, (U32)size);
|
printf("Alloc(%s) %s:%d %u\n", a->debug_name.str, thread_ctx.file, thread_ctx.line, (U32)size);
|
||||||
#endif
|
#endif
|
||||||
@@ -759,7 +721,7 @@ exp__alloc(Allocator *a, SizeU size, Alloc_Flag flag = AF_None){
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
force_inline void *
|
force_inline void *
|
||||||
exp__resize(Allocator *a, void *pointer, SizeU size){
|
exp__resize(Allocator *a, void *pointer, size_t size){
|
||||||
#if REPORT_ALLOCATIONS
|
#if REPORT_ALLOCATIONS
|
||||||
printf("Resize(%s) %s:%d %u\n", a->debug_name.str, thread_ctx.file, thread_ctx.line, (U32)size);
|
printf("Resize(%s) %s:%d %u\n", a->debug_name.str, thread_ctx.file, thread_ctx.line, (U32)size);
|
||||||
#endif
|
#endif
|
||||||
@@ -801,10 +763,6 @@ thread_ctx_init(){
|
|||||||
arena_init(thread_ctx.scratch, "Scratch1"_s);
|
arena_init(thread_ctx.scratch, "Scratch1"_s);
|
||||||
arena_init(thread_ctx.scratch+1, "Scratch2"_s);
|
arena_init(thread_ctx.scratch+1, "Scratch2"_s);
|
||||||
arena_init(&pernament_arena, "Pernament Arena"_s);
|
arena_init(&pernament_arena, "Pernament Arena"_s);
|
||||||
os_process_heap.proc = os_heap_allocator_proc;
|
|
||||||
os_process_heap.handle = GetProcessHeap();
|
|
||||||
os_process_heap.debug_name = "Win32 Process Heap"_s;
|
|
||||||
os_process_heap.kind = Allocator_OSHeap;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -847,7 +805,7 @@ struct Array{
|
|||||||
|
|
||||||
S64 get_index(T *item){
|
S64 get_index(T *item){
|
||||||
assert((data <= item) && ((data + len) > item));
|
assert((data <= item) && ((data + len) > item));
|
||||||
SizeU offset = item - data;
|
size_t offset = item - data;
|
||||||
return (S64)offset;
|
return (S64)offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1145,12 +1103,12 @@ function void
|
|||||||
map_test(){
|
map_test(){
|
||||||
Scratch scratch;
|
Scratch scratch;
|
||||||
Map map = {scratch};
|
Map map = {scratch};
|
||||||
const SizeU size = 1025;
|
const size_t size = 1025;
|
||||||
for(SizeU i = 1; i < size; i++){
|
for(size_t i = 1; i < size; i++){
|
||||||
map_insert(&map, i, (void *)i);
|
map_insert(&map, i, (void *)i);
|
||||||
}
|
}
|
||||||
for(SizeU i = 1; i < size; i++){
|
for(size_t i = 1; i < size; i++){
|
||||||
SizeU val = (SizeU)map_get(&map, i);
|
size_t val = (size_t)map_get(&map, i);
|
||||||
assert(val == i);
|
assert(val == i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1208,7 +1166,7 @@ test_intern_table(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
function Arena
|
function Arena
|
||||||
arena_sub(Allocator *base, SizeU size, String debug_name) {
|
arena_sub(Allocator *base, size_t size, String debug_name) {
|
||||||
Arena result = {};
|
Arena result = {};
|
||||||
result.memory.data = (U8 *)exp_alloc(base, size);
|
result.memory.data = (U8 *)exp_alloc(base, size);
|
||||||
result.memory.commit = size;
|
result.memory.commit = size;
|
||||||
@@ -1443,7 +1401,7 @@ T pop(List<T> *list){
|
|||||||
template<class T>
|
template<class T>
|
||||||
T *merge(Arena *arena, List<T> *list){
|
T *merge(Arena *arena, List<T> *list){
|
||||||
int len = length(list);
|
int len = length(list);
|
||||||
T *result = push_array(arena, T, len);
|
T *result = exp_alloc_array(arena, T, len);
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
For_Linked_List(list->first){
|
For_Linked_List(list->first){
|
||||||
|
|||||||
@@ -141,7 +141,7 @@ struct String_Builder{
|
|||||||
assert(!last && !first);
|
assert(!last && !first);
|
||||||
}
|
}
|
||||||
|
|
||||||
void push_block(SizeU size){
|
void push_block(size_t size){
|
||||||
String_Builder_Block *block = 0;
|
String_Builder_Block *block = 0;
|
||||||
if(first_free){
|
if(first_free){
|
||||||
block = first_free;
|
block = first_free;
|
||||||
@@ -218,7 +218,7 @@ function String
|
|||||||
string_flatten(Allocator *a, String_Builder *b, String_Builder_Flag flags = String_Builder_Flag_None){
|
string_flatten(Allocator *a, String_Builder *b, String_Builder_Flag flags = String_Builder_Flag_None){
|
||||||
// @Note(Krzosa): Compute size to allocate
|
// @Note(Krzosa): Compute size to allocate
|
||||||
S64 size = 1;
|
S64 size = 1;
|
||||||
if(is_flag_set(flags, String_Builder_Flag_AddSize)) size += sizeof(SizeU);
|
if(is_flag_set(flags, String_Builder_Flag_AddSize)) size += sizeof(size_t);
|
||||||
For_Linked_List(b->first){
|
For_Linked_List(b->first){
|
||||||
size += it->len;
|
size += it->len;
|
||||||
}
|
}
|
||||||
@@ -308,8 +308,8 @@ string_get_prefix(String string, S64 len) {
|
|||||||
|
|
||||||
function String
|
function String
|
||||||
string_slice(String string, S64 first_index, S64 one_past_last_index) {
|
string_slice(String string, S64 first_index, S64 one_past_last_index) {
|
||||||
assert_msg(first_index < one_past_last_index, "string_slice, first_index is bigger then one_past_last_index");
|
assert_message(first_index < one_past_last_index, "string_slice, first_index is bigger then one_past_last_index");
|
||||||
assert_msg(string.len > 0, "Slicing string of length 0! Might be an error!");
|
assert_message(string.len > 0, "Slicing string of length 0! Might be an error!");
|
||||||
String result = string;
|
String result = string;
|
||||||
if (string.len > 0) {
|
if (string.len > 0) {
|
||||||
if (one_past_last_index > first_index) {
|
if (one_past_last_index > first_index) {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
// Copyright (c) 2019 Christoffer Lerno. All rights reserved.
|
// Copyright (c) 2019 Christoffer Lerno. All rights reserved.
|
||||||
// Use of this source code is governed by the GNU LGPLv3.0 license
|
// Use of this source code is governed by the GNU LGPLv3.0 license
|
||||||
// a copy of which can be found in the LICENSE file.
|
// a copy of which can be found in the LICENSE file.
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#define Set_BigInt_Allocator(x) BigInt_Allocator bigint_allocator(x)
|
#define Set_BigInt_Allocator(x) BigInt_Allocator bigint_allocator(x)
|
||||||
struct BigInt_Allocator{
|
struct BigInt_Allocator{
|
||||||
|
|||||||
@@ -236,7 +236,7 @@ How does current declaration order resolver works:
|
|||||||
struct Ast_Scope: Ast{
|
struct Ast_Scope: Ast{
|
||||||
String debug_name; // Dont use
|
String debug_name; // Dont use
|
||||||
List<Ast_Scope *> implicit_imports;
|
List<Ast_Scope *> implicit_imports;
|
||||||
Array<Ast_Decl *> decls;
|
List<Ast_Decl *> decls;
|
||||||
Array<Ast *> stmts;
|
Array<Ast *> stmts;
|
||||||
|
|
||||||
U32 visit_id;
|
U32 visit_id;
|
||||||
@@ -301,7 +301,7 @@ struct Ast_Decl: Ast{
|
|||||||
|
|
||||||
#define ast_new(T,kind,pos,flags) (T *)_ast_new(sizeof(T), kind, pos, flags)
|
#define ast_new(T,kind,pos,flags) (T *)_ast_new(sizeof(T), kind, pos, flags)
|
||||||
function Ast *
|
function Ast *
|
||||||
_ast_new(SizeU size, Ast_Kind kind, Token *pos, Ast_Flag flags = 0){
|
_ast_new(size_t size, Ast_Kind kind, Token *pos, Ast_Flag flags = 0){
|
||||||
Ast *result = (Ast *)exp_alloc(pctx->perm, size, AF_ZeroMemory);
|
Ast *result = (Ast *)exp_alloc(pctx->perm, size, AF_ZeroMemory);
|
||||||
result->flags = flags;
|
result->flags = flags;
|
||||||
result->kind = kind;
|
result->kind = kind;
|
||||||
@@ -471,7 +471,6 @@ ast_array(Token *pos, Ast_Expr *expr){
|
|||||||
function Ast_Scope *
|
function Ast_Scope *
|
||||||
begin_decl_scope(Allocator *scratch, Token *pos){
|
begin_decl_scope(Allocator *scratch, Token *pos){
|
||||||
AST_NEW(Scope, SCOPE, pos, AST_DECL);
|
AST_NEW(Scope, SCOPE, pos, AST_DECL);
|
||||||
result->decls = {scratch};
|
|
||||||
result->file = pctx->currently_parsed_file;
|
result->file = pctx->currently_parsed_file;
|
||||||
result->module = pctx->currently_parsed_file->module;
|
result->module = pctx->currently_parsed_file->module;
|
||||||
result->scope_id = pctx->scope_ids++;
|
result->scope_id = pctx->scope_ids++;
|
||||||
@@ -483,7 +482,6 @@ begin_decl_scope(Allocator *scratch, Token *pos){
|
|||||||
|
|
||||||
function void
|
function void
|
||||||
finalize_decl_scope(Ast_Scope *scope){
|
finalize_decl_scope(Ast_Scope *scope){
|
||||||
scope->decls = scope->decls.tight_copy(pctx->perm);
|
|
||||||
pctx->currently_parsed_scope = scope->parent_scope;
|
pctx->currently_parsed_scope = scope->parent_scope;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -491,7 +489,6 @@ function Ast_Scope *
|
|||||||
begin_stmt_scope(Allocator *scratch, Token *pos){
|
begin_stmt_scope(Allocator *scratch, Token *pos){
|
||||||
AST_NEW(Scope, SCOPE, pos, AST_STMT);
|
AST_NEW(Scope, SCOPE, pos, AST_STMT);
|
||||||
result->stmts = {scratch};
|
result->stmts = {scratch};
|
||||||
result->decls = {pctx->heap};
|
|
||||||
result->file = pctx->currently_parsed_file;
|
result->file = pctx->currently_parsed_file;
|
||||||
result->module = pctx->currently_parsed_file->module;
|
result->module = pctx->currently_parsed_file->module;
|
||||||
result->scope_id = pctx->scope_ids++;
|
result->scope_id = pctx->scope_ids++;
|
||||||
@@ -559,7 +556,6 @@ ast_type(Token *pos, Intern_String name, Ast_Type *type){
|
|||||||
function Ast_Scope *
|
function Ast_Scope *
|
||||||
ast_decl_scope(Token *pos, Allocator *allocator, Ast_File *file){
|
ast_decl_scope(Token *pos, Allocator *allocator, Ast_File *file){
|
||||||
AST_NEW(Scope, SCOPE, pos, AST_DECL);
|
AST_NEW(Scope, SCOPE, pos, AST_DECL);
|
||||||
result->decls = {allocator};
|
|
||||||
result->file = file;
|
result->file = file;
|
||||||
|
|
||||||
result->scope_id = pctx->scope_ids++;
|
result->scope_id = pctx->scope_ids++;
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ function String
|
|||||||
string_scope_name(Allocator *a, Ast_Scope *scope){
|
string_scope_name(Allocator *a, Ast_Scope *scope){
|
||||||
String string = {};
|
String string = {};
|
||||||
if(scope->parent_scope) string = string_scope_name(a, scope->parent_scope);
|
if(scope->parent_scope) string = string_scope_name(a, scope->parent_scope);
|
||||||
assert_msg(scope->scope_id != 0, "Scope id is equal to 0 which is invalid, scope didn't initialize id");
|
assert_message(scope->scope_id != 0, "Scope id is equal to 0 which is invalid, scope didn't initialize id");
|
||||||
string = string_fmt(a, "%QS%u_", string, scope->scope_id);
|
string = string_fmt(a, "%QS%u_", string, scope->scope_id);
|
||||||
return string;
|
return string;
|
||||||
}
|
}
|
||||||
@@ -673,9 +673,9 @@ gen_ast(Ast *ast){
|
|||||||
gen("%Q{", node->unique_name);
|
gen("%Q{", node->unique_name);
|
||||||
global_indent++;
|
global_indent++;
|
||||||
is_inside_struct++;
|
is_inside_struct++;
|
||||||
For(node->scope->decls){
|
Iter(&node->scope->decls){
|
||||||
genln("");
|
genln("");
|
||||||
gen_ast(it);
|
gen_ast(it.item[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
is_inside_struct--;
|
is_inside_struct--;
|
||||||
@@ -688,10 +688,10 @@ gen_ast(Ast *ast){
|
|||||||
gen("/*enum %Q{", node->name);
|
gen("/*enum %Q{", node->name);
|
||||||
// @todo add typespec
|
// @todo add typespec
|
||||||
global_indent++;
|
global_indent++;
|
||||||
For(node->scope->decls){
|
Iter(&node->scope->decls){
|
||||||
genln("%Q", it->name);
|
genln("%Q", it.item[0]->name);
|
||||||
gen(" = ");
|
gen(" = ");
|
||||||
gen_value(it->pos, it->value);
|
gen_value(it.item[0]->pos, it.item[0]->value);
|
||||||
gen(",");
|
gen(",");
|
||||||
}
|
}
|
||||||
global_indent--;
|
global_indent--;
|
||||||
|
|||||||
@@ -196,7 +196,6 @@ add_module(Token *pos, Intern_String filename, B32 command_line_module){
|
|||||||
result->debug_name = string_skip_to_last_slash(result->absolute_file_path);
|
result->debug_name = string_skip_to_last_slash(result->absolute_file_path);
|
||||||
result->module = result; // @warning: self referential
|
result->module = result; // @warning: self referential
|
||||||
result->file = result; // @warning: self referential
|
result->file = result; // @warning: self referential
|
||||||
result->decls = {pctx->heap};
|
|
||||||
result->parent_scope = 0;
|
result->parent_scope = 0;
|
||||||
result->scope_id = pctx->scope_ids++;
|
result->scope_id = pctx->scope_ids++;
|
||||||
|
|
||||||
@@ -210,11 +209,12 @@ resolve_everything_in_module(Ast_Module *module){
|
|||||||
if(module->state == MODULE_RESOLVED) return;
|
if(module->state == MODULE_RESOLVED) return;
|
||||||
resolving_time_begin = os_time();
|
resolving_time_begin = os_time();
|
||||||
Iter_Named(&module->all_loaded_files, file){
|
Iter_Named(&module->all_loaded_files, file){
|
||||||
For(file.item[0]->decls){
|
Iter(&file.item[0]->decls){
|
||||||
resolve_name(file.item[0], it->pos, it->name);
|
Ast_Decl *decl = it.item[0];
|
||||||
|
resolve_name(file.item[0], decl->pos, decl->name);
|
||||||
|
|
||||||
if(it->kind == AST_STRUCT){
|
if(decl->kind == AST_STRUCT){
|
||||||
type_complete(it->type_val);
|
type_complete(decl->type_val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,8 +45,8 @@ Intern_String intern_it;
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Type globals
|
// Type globals
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
const SizeU pointer_size = sizeof(SizeU);
|
const uintptr_t pointer_size = sizeof(uintptr_t);
|
||||||
const SizeU pointer_align = __alignof(SizeU);
|
const uintptr_t pointer_align = __alignof(uintptr_t);
|
||||||
global Ast_Type type__void = {TYPE_VOID};
|
global Ast_Type type__void = {TYPE_VOID};
|
||||||
global Ast_Type type__string = {TYPE_STRING, sizeof(String), __alignof(String)};
|
global Ast_Type type__string = {TYPE_STRING, sizeof(String), __alignof(String)};
|
||||||
global Ast_Type type__bool = {TYPE_BOOL, sizeof(bool), __alignof(bool)};
|
global Ast_Type type__bool = {TYPE_BOOL, sizeof(bool), __alignof(bool)};
|
||||||
|
|||||||
@@ -1,10 +1,14 @@
|
|||||||
/*
|
/*
|
||||||
|
|
||||||
First doable version:
|
Current:
|
||||||
|
|
||||||
|
- [ ] Foreign import that would link library
|
||||||
|
- [ ] String in Language.core
|
||||||
|
- [ ] Way to import and force evaluate #import_lazy #import ?
|
||||||
|
- [ ] Unix port
|
||||||
|
|
||||||
- [ ] Imports are leaking names ! Multimedia leaks windows stuff
|
- [ ] Imports are leaking names ! Multimedia leaks windows stuff
|
||||||
- [ ] Test and bulletproof any, slices
|
- [ ] Test and bulletproof any, slices
|
||||||
- [ ] Include multiple pattern matched imports "unix_" and "linux_" both should be included on linux
|
|
||||||
|
|
||||||
In the future
|
In the future
|
||||||
|
|
||||||
@@ -12,7 +16,6 @@ In the future
|
|||||||
- [ ] Add ability to do i: int = 0 inside for loops for i: int = 0, i < 10, i+=1
|
- [ ] Add ability to do i: int = 0 inside for loops for i: int = 0, i < 10, i+=1
|
||||||
- [ ] Complicated c declaration generation
|
- [ ] Complicated c declaration generation
|
||||||
|
|
||||||
- [ ] Way to import and force evaluate #import_lazy #import ?
|
|
||||||
- [ ] Expand macros
|
- [ ] Expand macros
|
||||||
- [ ] Defer
|
- [ ] Defer
|
||||||
|
|
||||||
@@ -37,15 +40,16 @@ In the future
|
|||||||
|
|
||||||
- [ ] Parametric Polymorphism
|
- [ ] Parametric Polymorphism
|
||||||
|
|
||||||
- [ ] Conditional compilation #if (maybe just do something like a conditional load or import?) #import "windows.kl" when os == "windows"
|
Ideas
|
||||||
|
- [ ] #test construct that would gather all tests and run them on start of program or something
|
||||||
- [ ] Any
|
- [ ] Inject stack traces into the program
|
||||||
- [ ] Assigning to any values like ints etc. should work perhaps? But what type they should have?
|
- [ ] Constant arrays that evaluate fully at compile time
|
||||||
- [ ] Slice of Any should work well
|
- [ ] Rust like enum where you associate values(other structs) with key
|
||||||
|
- [ ] Cast from array to pointer?
|
||||||
Maybe later
|
- [ ] Ternary operator?
|
||||||
- [ ] Optionally pass size and alignment calculations to C ?
|
- [ ] Optionally pass size and alignment calculations to C ?
|
||||||
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
2022.09.29 - Function overloads, operator overloads, namespaces idea
|
2022.09.29 - Function overloads, operator overloads, namespaces idea
|
||||||
@@ -117,36 +121,6 @@ For modules it's a bit different cause they should be distributed as valid.
|
|||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
- [ ] Probably need to give Ast_Expr a Value field, then I can express Type nicely
|
|
||||||
- [ ] I would love for String, slice, Any etc. to have their struct declarations in source files, I also would want for stuff like string.str to work without weird special cases
|
|
||||||
- [ ] Var args with Any
|
|
||||||
|
|
||||||
- [ ] #test construct that would gather all tests and run them on start of program or something
|
|
||||||
- [ ] Foreign import that would link library
|
|
||||||
- [ ] Kilobyte, Megabyte, Gigabyte
|
|
||||||
- [ ] Cast from array to pointer?
|
|
||||||
- [ ] Fix field access, cant cast, cant index
|
|
||||||
- [ ] Add parent_scope to Ast_Type, Add name to Ast_Type?
|
|
||||||
|
|
||||||
- [ ] Optional function renaming in codegen
|
|
||||||
- [ ] Using in structs to embed members, then casting offsets to that embedded member
|
|
||||||
|
|
||||||
- [ ] Comma notation when declaring variables thing1, thing2: S32 :: probably want to unify it with var unpacking
|
|
||||||
- [ ] Add single line lambda expressions
|
|
||||||
- [ ] Ternary operator
|
|
||||||
- [ ] Write up on order independent declarations
|
|
||||||
|
|
||||||
- [ ] constructor => thing :: (i: S32) -> {i = i, thing = 10}
|
|
||||||
- [ ] Default values in structs??? Should compound stmts bring values from default values?? Maybe not? Whats the alternative
|
|
||||||
|
|
||||||
@ideas
|
|
||||||
- [ ] Var args using Any array - args: []Any - delete vargs
|
|
||||||
- [ ] Constant arrays that evaluate fully at compile time
|
|
||||||
- [ ] Rust like enum where you associate values(other structs) with keys
|
|
||||||
- [ ] Compound that zeros values - .{} , Compound that assumes defaults from struct definition - {}
|
|
||||||
- [ ] Inject stack traces into the program
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Done
|
## Done
|
||||||
|
|
||||||
@@ -247,7 +221,15 @@ For modules it's a bit different cause they should be distributed as valid.
|
|||||||
|
|
||||||
#include "base.cpp"
|
#include "base.cpp"
|
||||||
#include "base_unicode.cpp"
|
#include "base_unicode.cpp"
|
||||||
|
|
||||||
|
#if OS_WINDOWS
|
||||||
#include "os_windows.cpp"
|
#include "os_windows.cpp"
|
||||||
|
#elif OS_UNIX
|
||||||
|
#include "os_unix.cpp"
|
||||||
|
#else
|
||||||
|
#error Couldnt figure out OS using macros
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "c3_big_int.h"
|
#include "c3_big_int.h"
|
||||||
#include "core_compiler.h"
|
#include "core_compiler.h"
|
||||||
#include "core_types.h"
|
#include "core_types.h"
|
||||||
@@ -307,5 +289,5 @@ int main(int argument_count, char **arguments){
|
|||||||
compile_file(it.absolute_path, COMPILE_AND_RUN | COMPILE_TESTING);
|
compile_file(it.absolute_path, COMPILE_AND_RUN | COMPILE_TESTING);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
__debugbreak();
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ compiler_error(Token *token1, Token *token2, const char *str, ...){
|
|||||||
if(token1) printf("\n%s:%d token_di:%u", token1->file.str, (S32)token1->line + 1, token1->di);
|
if(token1) printf("\n%s:%d token_di:%u", token1->file.str, (S32)token1->line + 1, token1->di);
|
||||||
if(token2) printf("\n%s:%d token_di:%u", token2->file.str, (S32)token2->line + 1, token2->di);
|
if(token2) printf("\n%s:%d token_di:%u", token2->file.str, (S32)token2->line + 1, token2->di);
|
||||||
|
|
||||||
__debugbreak();
|
Breakpoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
function void
|
function void
|
||||||
@@ -72,7 +72,7 @@ compiler_error(Token *token, const char *str, ...){
|
|||||||
|
|
||||||
if(token) printf("\n%s:%d token_di:%u", token->file.str, (S32)token->line + 1, token->di);
|
if(token) printf("\n%s:%d token_di:%u", token->file.str, (S32)token->line + 1, token->di);
|
||||||
|
|
||||||
__debugbreak();
|
Breakpoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Token *
|
function Token *
|
||||||
@@ -678,7 +678,7 @@ parse_struct(Token *pos){
|
|||||||
Ast_Decl *decl = ast_var(token, typespec, token->intern_val, 0);
|
Ast_Decl *decl = ast_var(token, typespec, token->intern_val, 0);
|
||||||
decl->flags = set_flag(decl->flags, AST_AGGREGATE_CHILD);
|
decl->flags = set_flag(decl->flags, AST_AGGREGATE_CHILD);
|
||||||
|
|
||||||
scope->decls.add(decl);
|
add(pctx->perm, &scope->decls, decl);
|
||||||
|
|
||||||
}while(token_match(SAME_SCOPE));
|
}while(token_match(SAME_SCOPE));
|
||||||
token_expect(CLOSE_SCOPE);
|
token_expect(CLOSE_SCOPE);
|
||||||
@@ -702,7 +702,7 @@ parse_enum(Token *pos){
|
|||||||
if(token_match(TK_DoubleColon)) value = parse_expr();
|
if(token_match(TK_DoubleColon)) value = parse_expr();
|
||||||
Ast_Decl *member = ast_const(name, name->intern_val, value);
|
Ast_Decl *member = ast_const(name, name->intern_val, value);
|
||||||
member->flags = set_flag(member->flags, AST_AGGREGATE_CHILD);
|
member->flags = set_flag(member->flags, AST_AGGREGATE_CHILD);
|
||||||
scope->decls.add(member);
|
add(pctx->perm, &scope->decls, member);
|
||||||
}while(token_match(SAME_SCOPE));
|
}while(token_match(SAME_SCOPE));
|
||||||
finalize_decl_scope(scope);
|
finalize_decl_scope(scope);
|
||||||
token_expect(CLOSE_SCOPE);
|
token_expect(CLOSE_SCOPE);
|
||||||
@@ -753,7 +753,6 @@ register_ast_file(Token *pos, String absolute_file_path, Ast_Module *module, B32
|
|||||||
file->module = module;
|
file->module = module;
|
||||||
file->parent_scope = 0;
|
file->parent_scope = 0;
|
||||||
file->file = file; // @warning: self referential!
|
file->file = file; // @warning: self referential!
|
||||||
file->decls = {pctx->heap};
|
|
||||||
file->pos = pos;
|
file->pos = pos;
|
||||||
file->debug_name = string_skip_to_last_slash(absolute_file_path);
|
file->debug_name = string_skip_to_last_slash(absolute_file_path);
|
||||||
add(pctx->perm, &file->module->all_loaded_files, file);
|
add(pctx->perm, &file->module->all_loaded_files, file);
|
||||||
|
|||||||
@@ -443,9 +443,10 @@ inside_scope_search(Scope_Search *search, Ast_Scope *scope, int level){
|
|||||||
scope->visit_id = search->scope_visit_id;
|
scope->visit_id = search->scope_visit_id;
|
||||||
|
|
||||||
// Search for declarations in current scope
|
// Search for declarations in current scope
|
||||||
For(scope->decls){
|
Iter(&scope->decls){
|
||||||
if(it->name == search->name){
|
Ast_Decl *decl = it.item[0];
|
||||||
search->results.add(it);
|
if(decl->name == search->name){
|
||||||
|
search->results.add(decl);
|
||||||
if(search->exit_on_find){
|
if(search->exit_on_find){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -591,7 +592,7 @@ insert_into_scope(Ast_Scope *scope, Ast_Decl *decl){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
scope->decls.add(decl);
|
add(pctx->perm, &scope->decls, decl);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -1686,13 +1687,14 @@ resolve_decl(Ast_Decl *ast){
|
|||||||
node->type_val = type_enum(node, type_of_enum);
|
node->type_val = type_enum(node, type_of_enum);
|
||||||
|
|
||||||
S64 value = 1;
|
S64 value = 1;
|
||||||
For(node->scope->decls){
|
Iter(&node->scope->decls){
|
||||||
|
Ast_Decl *decl = it.item[0];
|
||||||
Operand op = {};
|
Operand op = {};
|
||||||
if(it->expr){
|
if(decl->expr){
|
||||||
op = require_const_int(it->expr, AST_CANT_BE_NULL);
|
op = require_const_int(decl->expr, AST_CANT_BE_NULL);
|
||||||
value = bigint_as_signed(&op.big_int_val) + 1;
|
value = bigint_as_signed(&op.big_int_val) + 1;
|
||||||
} else{
|
} else{
|
||||||
it->state = DECL_RESOLVED;
|
decl->state = DECL_RESOLVED;
|
||||||
op.type = node->type_val;
|
op.type = node->type_val;
|
||||||
bigint_init_signed(&op.big_int_val, value);
|
bigint_init_signed(&op.big_int_val, value);
|
||||||
if(is_flag_set(node->flags, AST_FLAG)){
|
if(is_flag_set(node->flags, AST_FLAG)){
|
||||||
@@ -1702,7 +1704,7 @@ resolve_decl(Ast_Decl *ast){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
it->value = op.value;
|
decl->value = op.value;
|
||||||
}
|
}
|
||||||
BREAK();
|
BREAK();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ force_inline B32 is_numeric(Ast_Type *type){
|
|||||||
// Hash consed types
|
// Hash consed types
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
function Ast_Type *
|
function Ast_Type *
|
||||||
type_new(Allocator *allocator, Ast_Type_Kind kind, SizeU size, SizeU align){
|
type_new(Allocator *allocator, Ast_Type_Kind kind, size_t size, size_t align){
|
||||||
Ast_Type *result = exp_alloc_type(allocator, Ast_Type, AF_ZeroMemory);
|
Ast_Type *result = exp_alloc_type(allocator, Ast_Type, AF_ZeroMemory);
|
||||||
result->kind = kind;
|
result->kind = kind;
|
||||||
result->size = size;
|
result->size = size;
|
||||||
@@ -230,19 +230,20 @@ type_struct_complete(Ast_Type *type, Ast_Decl *node){
|
|||||||
Array<Ast_Resolved_Member> members = {scratch};
|
Array<Ast_Resolved_Member> members = {scratch};
|
||||||
type->kind = TYPE_COMPLETING;
|
type->kind = TYPE_COMPLETING;
|
||||||
size_t members_size = 0;
|
size_t members_size = 0;
|
||||||
For(node->scope->decls){
|
Iter(&node->scope->decls){
|
||||||
resolve_decl(it);
|
Ast_Decl *decl = it.item[0];
|
||||||
assert(it->type->kind != TYPE_INCOMPLETE);
|
resolve_decl(decl);
|
||||||
assert(is_pow2(it->type->align));
|
assert(decl->type->kind != TYPE_INCOMPLETE);
|
||||||
|
assert(is_pow2(decl->type->align));
|
||||||
|
|
||||||
Ast_Resolved_Member m = {};
|
Ast_Resolved_Member m = {};
|
||||||
m.offset = type->size;
|
m.offset = type->size;
|
||||||
members_size += it->type->size;
|
members_size += decl->type->size;
|
||||||
type->align = max(type->align, it->type->align);
|
type->align = max(type->align, decl->type->align);
|
||||||
type->size = it->type->size + align_up(type->size, it->type->align);
|
type->size = decl->type->size + align_up(type->size, decl->type->align);
|
||||||
|
|
||||||
m.name = it->name;
|
m.name = decl->name;
|
||||||
m.value = it->value;
|
m.value = decl->value;
|
||||||
members.add(m);
|
members.add(m);
|
||||||
}
|
}
|
||||||
type->size = align_up(type->size, type->align);
|
type->size = align_up(type->size, type->align);
|
||||||
|
|||||||
@@ -1,27 +1,28 @@
|
|||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Memory
|
// Memory
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
const SizeU os_page_size = 4096;
|
const size_t os_page_size = 4096;
|
||||||
|
|
||||||
function OS_Memory
|
function OS_Memory
|
||||||
os_reserve(SizeU size){
|
os_reserve(size_t size){
|
||||||
OS_Memory result = {};
|
OS_Memory result = {};
|
||||||
SizeU adjusted_size = align_up(size, os_page_size);
|
size_t adjusted_size = align_up(size, os_page_size);
|
||||||
result.data = (U8*)VirtualAlloc(0, adjusted_size, MEM_RESERVE, PAGE_READWRITE);
|
result.data = (U8*)VirtualAlloc(0, adjusted_size, MEM_RESERVE, PAGE_READWRITE);
|
||||||
assert_msg(result.data, "Failed to reserve virtual memory");
|
assert_message(result.data, "Failed to reserve virtual memory");
|
||||||
result.reserve = adjusted_size;
|
result.reserve = adjusted_size;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function B32
|
function B32
|
||||||
os_commit(OS_Memory *m, SizeU size){
|
os_commit(OS_Memory *m, size_t size){
|
||||||
SizeU commit = align_up(size, os_page_size);
|
size_t commit = align_up(size, os_page_size);
|
||||||
SizeU total_commit = m->commit + commit;
|
size_t total_commit = m->commit + commit;
|
||||||
total_commit = clamp_top(total_commit, m->reserve);
|
total_commit = clamp_top(total_commit, m->reserve);
|
||||||
SizeU adjusted_commit = total_commit - m->commit;
|
size_t adjusted_commit = total_commit - m->commit;
|
||||||
if(adjusted_commit != 0){
|
if(adjusted_commit != 0){
|
||||||
void *result = VirtualAlloc((U8*)m->data + m->commit, adjusted_commit, MEM_COMMIT, PAGE_READWRITE);
|
void *result = VirtualAlloc((U8*)m->data + m->commit, adjusted_commit, MEM_COMMIT, PAGE_READWRITE);
|
||||||
assert_msg(result, "Failed to commit more memory");
|
assert_message(result, "Failed to commit more memory");
|
||||||
m->commit += adjusted_commit;
|
m->commit += adjusted_commit;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -31,7 +32,7 @@ os_commit(OS_Memory *m, SizeU size){
|
|||||||
function void
|
function void
|
||||||
os_release(OS_Memory *m){
|
os_release(OS_Memory *m){
|
||||||
BOOL result = VirtualFree(m->data, 0, MEM_RELEASE);
|
BOOL result = VirtualFree(m->data, 0, MEM_RELEASE);
|
||||||
assert_msg(result != 0, "Failed to release OS_Memory");
|
assert_message(result != 0, "Failed to release OS_Memory");
|
||||||
if(result){
|
if(result){
|
||||||
m->data = 0;
|
m->data = 0;
|
||||||
m->commit = 0;
|
m->commit = 0;
|
||||||
@@ -40,10 +41,10 @@ os_release(OS_Memory *m){
|
|||||||
}
|
}
|
||||||
|
|
||||||
function B32
|
function B32
|
||||||
os_decommit_pos(OS_Memory *m, SizeU pos){
|
os_decommit_pos(OS_Memory *m, size_t pos){
|
||||||
SizeU aligned = align_down(pos, os_page_size);
|
size_t aligned = align_down(pos, os_page_size);
|
||||||
SizeU adjusted_pos = clamp_top(aligned, m->commit);
|
size_t adjusted_pos = clamp_top(aligned, m->commit);
|
||||||
SizeU size_to_decommit = m->commit - adjusted_pos;
|
size_t size_to_decommit = m->commit - adjusted_pos;
|
||||||
if(size_to_decommit){
|
if(size_to_decommit){
|
||||||
U8 *base_address = m->data + adjusted_pos;
|
U8 *base_address = m->data + adjusted_pos;
|
||||||
BOOL result = VirtualFree(base_address, size_to_decommit, MEM_DECOMMIT);
|
BOOL result = VirtualFree(base_address, size_to_decommit, MEM_DECOMMIT);
|
||||||
@@ -247,3 +248,56 @@ os_list_dir(Allocator *a, String dir, U32 flags = LIST_NO_FLAGS){
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// OS Heap allocator
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
struct OS_Heap:Allocator{
|
||||||
|
void *handle;
|
||||||
|
};
|
||||||
|
|
||||||
|
function void *
|
||||||
|
os_heap_allocator_proc(Allocator *a, Allocation_Kind kind, void *old_pointer, size_t size){
|
||||||
|
OS_Heap *heap = (OS_Heap *)a;
|
||||||
|
switch(kind){
|
||||||
|
case Allocation_FreeAll:{
|
||||||
|
invalid_codepath;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
case Allocation_Destroy:{
|
||||||
|
BOOL result = HeapDestroy(heap->handle);
|
||||||
|
assert(result != 0);
|
||||||
|
heap->handle = 0;
|
||||||
|
heap->proc = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
case Allocation_Free:{
|
||||||
|
BOOL result = HeapFree(heap->handle, 0, old_pointer);
|
||||||
|
assert(result != 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
case Allocation_Alloc:{
|
||||||
|
void *result = HeapAlloc(heap->handle, 0, size);
|
||||||
|
assert(result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
case Allocation_Resize:{
|
||||||
|
void *result = HeapReAlloc(heap->handle, 0, old_pointer, size);
|
||||||
|
assert(result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
default: invalid_codepath;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function OS_Heap // max_size == 0 == growing heap
|
||||||
|
win32_os_heap_create(B32 multithreaded, size_t initial_size, size_t max_size, String debug_name){
|
||||||
|
OS_Heap result = {};
|
||||||
|
result.debug_name = debug_name;
|
||||||
|
result.proc = os_heap_allocator_proc;
|
||||||
|
result.kind = Allocator_OSHeap;
|
||||||
|
result.handle = HeapCreate(multithreaded ? 0 : HEAP_NO_SERIALIZE, initial_size, max_size);
|
||||||
|
assert(result.handle);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user