diff --git a/Odin/watl.v0.odin b/Odin/watl.v0.odin new file mode 100644 index 0000000..06511fb --- /dev/null +++ b/Odin/watl.v0.odin @@ -0,0 +1,131 @@ +/* +WATL Exercise +Version: 0 (From Scratch, 1-Stage Compilation, MSVC & WinAPI Only, Win CRT Multi-threaded Static Linkage) +Host: Windows 11 (x86-64) +Toolchain: odin-lang/Odin dev-2025-06 +*/ +package odin + +import "base:builtin" +import "base:intrinsics" + +//#region("Package Mappings") +abs :: builtin.abs +min :: builtin.min +max :: builtin.max +clamp :: builtin.clamp + +copy :: proc { + memory_copy, + slice_copy, +} +copy_non_overlapping :: proc { + memory_copy_non_overlapping, + slice_copy_non_overlapping, +} +end :: proc { + slice_end, +} +zero :: proc { + memory_zero, + slice_zero, +} +zero_explicit :: proc { + memory_zero_explicit, +} +//#endregion("Package Mappings") + +//#region("Memory") +align_pow2 :: proc(x: int, b: int) -> int { + assert(b != 0) + assert((b & (b - 1)) == 0) // Check power of 2 + return ((x + b - 1) & ~(b - 1)) +} +memory_zero :: proc "contextless" (data: rawptr, len: int) -> rawptr { + intrinsics.mem_zero(data, len) + return data +} +memory_zero_explicit :: proc "contextless" (data: rawptr, len: int) -> rawptr { + intrinsics.mem_zero_volatile(data, len) // Use the volatile mem_zero + intrinsics.atomic_thread_fence(.Seq_Cst) // Prevent reordering + return data +} +memory_copy :: proc "contextless" (dst, src: rawptr, len: int) -> rawptr { + intrinsics.mem_copy(dst, src, len) + return dst +} +memory_copy_non_overlapping :: proc "contextless" (dst, src: rawptr, len: int) -> rawptr { + intrinsics.mem_copy_non_overlapping(dst, src, len) + return dst +} + +Raw_Slice :: struct { + data: rawptr, + len: int, +} + +slice_assert :: proc "contextless" (s: $Type / []$SliceType) -> Type { + return assert(len(s) > 0) && s != nil +} +slice_end :: proc "contextless" (s : $Type / []$SliceType) -> Type { + return s[len(s) - 1] +} +size_of_slice_type :: proc(slice: $Type / []$SliceType) -> int { + return size_of(E) +} + +@(require_results) +to_bytes :: proc "contextless" (s: []$Type) -> []byte { + return ([^]byte)(raw_data(s))[:len(s) * size_of(T)] +} + +slice_zero :: proc "contextless" (data: $Type / []$SliceType) -> Type { + zero(raw_data(data), size_of(E) * len(data)) + return data +} +slice_copy :: proc "contextless" (dst, src: $Ttype / []$SliceType) -> int { + n := max(0, min(len(dst), len(src))) + if n > 0 { + intrinsics.mem_copy(raw_data(dst), raw_data(src), n*size_of(E)) + } + return n +} +slice_copy_non_overlapping :: proc "contextless" (dst, src: $Type / []$SliceType) -> int { + n := max(0, min(len(dst), len(src))) + if n > 0 { + intrinsics.mem_copy_non_overlapping(raw_data(dst), raw_data(src), n*size_of(E)) + } + return n +} + +sll_stack_push_n :: proc(first: ^$SLL_NodeType, n: ^SLL_NodeType) { + n.next = first^ + first^ = n +} +sll_queue_push_nz :: proc(nil_val: ^$SLL_NodeType, first: ^SLL_NodeType, last: ^SLL_NodeType, n: ^SLL_NodeType) { + if first^ == nil_val { + first^ = n + last^ = n + n.next = nil_val + } else { + last^.next = n + last^ = n + n.next = nil_val + } +} +sll_queue_push_n :: proc(first: ^$SLL_NodeType, last: ^SLL_NodeType, n: ^SLL_NodeType) { + sll_queue_push_nz(nil, first, last, n) +} +//#endregion("Memory") + +//#region("Strings") +Raw_String :: struct { + data: [^]byte, + len: int, +} +//#endregion("Strings") + +main :: proc() +{ + +} diff --git a/scripts/build.ps1 b/scripts/build.c.ps1 similarity index 100% rename from scripts/build.ps1 rename to scripts/build.c.ps1 diff --git a/scripts/build.odin.odin b/scripts/build.odin.odin new file mode 100644 index 0000000..95e6133 --- /dev/null +++ b/scripts/build.odin.odin @@ -0,0 +1,120 @@ +package build + +//region Script Grime +import mem "core:mem" +import vmem "core:mem/virtual" +import os "core:os/os2" +import "core:fmt" +import _strings "core:strings" + StrGen :: _strings.Builder + strgen_init :: _strings.builder_init + strgen_join :: _strings.join + +join_path :: #force_inline proc(elems : ..string) -> string { res, _ := os.join_path(transmute([]string)elems, context.allocator); return transmute(string)res } +get_working_dir :: #force_inline proc() -> string { res, _ := os.get_working_directory(context.allocator); return transmute(string)res } + +join_str :: #force_inline proc(elems : ..string) -> string { + gen : StrGen; strgen_init(& gen, context.allocator) + res, _ := strgen_join(elems, "") + return res +} + +// For a beakdown of any flag, type -help +command_build :: "build" +command_check :: "check" +command_query :: "query" +command_report :: "report" +command_run :: "run" + +flag_build_mode :: "-build-mode:" +flag_build_mode_dll :: "-build-mode:dll" +flag_collection :: "-collection:" +flag_file :: "-file" +flag_debug :: "-debug" +flag_define :: "-define:" +flag_default_allocator_nil :: "-default-to-nil-allocator" +flag_disable_assert :: "-disable-assert" +flag_dynamic_map_calls :: "-dynamic-map-calls" +flag_extra_assembler_flags :: "-extra_assembler-flags:" +flag_extra_linker_flags :: "-extra-linker-flags:" +flag_ignore_unknown_attributes :: "-ignore-unknown-attributes" +flag_keep_temp_files :: "-keep-temp-files" +flag_max_error_count :: "-max-error-count:" +flag_micro_architecture_native :: "-microarch:native" +flag_no_bounds_check :: "-no-bounds-check" +flag_no_crt :: "-no-crt" +flag_no_entrypoint :: "-no-entry-point" +flag_no_thread_local :: "-no-thread-local" +flag_no_thread_checker :: "-no-threaded-checker" +flag_output_path :: "-out=" +flag_optimization_level :: "-opt:" +flag_optimize_none :: "-o:none" +flag_optimize_minimal :: "-o:minimal" +flag_optimize_size :: "-o:size" +flag_optimize_speed :: "-o:speed" +falg_optimize_aggressive :: "-o:aggressive" +flag_pdb_name :: "-pdb-name:" +flag_sanitize_address :: "-sanitize:address" +flag_sanitize_memory :: "-sanitize:memory" +flag_sanitize_thread :: "-sanitize:thread" +flag_subsystem :: "-subsystem:" +flag_show_debug_messages :: "-show-debug-messages" +flag_show_timings :: "-show-timings" +flag_show_more_timings :: "-show-more-timings" +flag_show_system_calls :: "-show-system-calls" +flag_target :: "-target:" +flag_thread_count :: "-thread-count:" +flag_use_lld :: "-linker:lld" +flag_use_rad_link :: "-linker:radlink" +flag_use_separate_modules :: "-use-separate-modules" +flag_vet_all :: "-vet" +flag_vet_unused_entities :: "-vet-unused" +flag_vet_semicolon :: "-vet-semicolon" +flag_vet_shadow_vars :: "-vet-shadowing" +flag_vet_using_stmt :: "-vet-using-stmt" + +flag_microarch_zen5 :: "--microarch:znver5" + +flag_msvc_link_disable_dynamic_base :: "/DYNAMICBASE:NO" +flag_msvc_link_base_address :: "/BASE:" +flag_msvc_link_fixed_base_address :: "/FIXED" +flag_msvc_link_stack_size :: "/STACK" +flag_msvc_link_debug :: "/DEBUG" + +msvc_link_default_base_address :: 0x180000000 +//endregion Script Grime + +build :: proc(working_dir : string, args : []string) -> (stdout : string, stderr : string) { + fmt.println("Building:", args) + res, errs : []byte; _, res, errs, _ = os.process_exec({ working_dir = working_dir, command = args}, context.allocator) + return transmute(string)res, transmute(string)errs; +} + +main :: proc() { + varena : vmem.Arena; _ = vmem.arena_init_growing(& varena, mem.Megabyte * 64 ); context.allocator = vmem.arena_allocator(& varena) + exe_odin :: "odin.exe" + + path_root := get_working_dir() + path_build := join_path(path_root, "build") + path_odin_src := join_path(path_root, "Odin") + file_source := join_path(path_odin_src, "watl.v0.odin") + file_exe := join_path(path_build, "watl.v0.exe") + + res, errs := build(path_build, { + exe_odin, + command_build, + file_source, + flag_file, + join_str(flag_output_path, file_exe), + flag_optimize_none, + flag_default_allocator_nil, + flag_debug, + flag_microarch_zen5, + flag_no_thread_checker, + flag_show_timings, + flag_use_rad_link, + join_str(flag_subsystem, "console"), + }) + fmt.println(res) + fmt.println(errs) +} diff --git a/scripts/build.odin.ps1 b/scripts/build.odin.ps1 new file mode 100644 index 0000000..50a4c9c --- /dev/null +++ b/scripts/build.odin.ps1 @@ -0,0 +1,41 @@ +$path_root = split-path -Path $PSScriptRoot -Parent +$path_build = join-path $path_root 'build' +$path_code = join-path $path_root 'code' + +$path_source = join-path $PSScriptRoot 'build.odin.odin' +$exe = join-path $path_build 'build_win32.exe' + +if ((test-path $path_build) -eq $false) { + new-item -itemtype directory -path $path_build +} + +$odin = 'odin.exe' + +$command_build = 'build' + +$flag_debug = '-debug' +$flag_file = '-file' +$flag_dyn_map_calls = '-dynamic-map-calls' +$flag_no_bounds_check = '-no-bounds-check' +$flag_no_threaded_checker = '-no-threaded-checker' +$flag_no_type_assert = '-no-type-assert' +$flag_optimize_none = '-o:none' +$flag_output_path = '-out=' +$flag_default_allocator_nil = '-default-to-nil-allocator' + +push-location $path_root +$build_args = @() +$build_args += $command_build +$build_args += $path_source +$build_args += $flag_file +# $build_args += $flag_debug +$build_args += $flag_optimize_none +$build_args += $flag_no_bounds_check +$build_args += $flag_no_threaded_checker +$build_args += $flag_no_type_assert +$build_args += $flag_dyn_map_calls +$build_args += $flag_default_allocator_nil +$build_args += $flag_output_path + $exe +# & $odin $build_args +& $exe +pop-location