Removing heap allocations, Porting to Unix

This commit is contained in:
Krzosa Karol
2022-10-09 10:34:23 +02:00
parent aa2b4d90e4
commit b22e1ac0db
13 changed files with 260 additions and 269 deletions

View File

@@ -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
View File

@@ -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){

View File

@@ -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) {

View File

@@ -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{

View File

@@ -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++;

View File

@@ -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--;

View File

@@ -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);
} }
} }
} }

View File

@@ -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)};

View File

@@ -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;
} }

View File

@@ -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);

View 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();
} }

View File

@@ -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);

View File

@@ -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;
}