diff --git a/core/runtime/internal_windows.odin b/core/runtime/internal_windows.odin index 913eec36f..52d6756b6 100644 --- a/core/runtime/internal_windows.odin +++ b/core/runtime/internal_windows.odin @@ -1,183 +1,5 @@ package runtime -@(default_calling_convention="none") -foreign { - @(link_name="llvm.cttz.i8") _ctz_u8 :: proc(i: u8, is_zero_undef := false) -> u8 --- - @(link_name="llvm.cttz.i16") _ctz_u16 :: proc(i: u16, is_zero_undef := false) -> u16 --- - @(link_name="llvm.cttz.i32") _ctz_u32 :: proc(i: u32, is_zero_undef := false) -> u32 --- - @(link_name="llvm.cttz.i64") _ctz_u64 :: proc(i: u64, is_zero_undef := false) -> u64 --- -} -_ctz :: proc{ - _ctz_u8, - _ctz_u16, - _ctz_u32, - _ctz_u64, -}; - -@(default_calling_convention="none") -foreign { - @(link_name="llvm.ctlz.i8") _clz_u8 :: proc(i: u8, is_zero_undef := false) -> u8 --- - @(link_name="llvm.ctlz.i16") _clz_u16 :: proc(i: u16, is_zero_undef := false) -> u16 --- - @(link_name="llvm.ctlz.i32") _clz_u32 :: proc(i: u32, is_zero_undef := false) -> u32 --- - @(link_name="llvm.ctlz.i64") _clz_u64 :: proc(i: u64, is_zero_undef := false) -> u64 --- -} -_clz :: proc{ - _clz_u8, - _clz_u16, - _clz_u32, - _clz_u64, -}; - - -udivmod128 :: proc "c" (a, b: u128, rem: ^u128) -> u128 { - n := transmute([2]u64)a; - d := transmute([2]u64)b; - q, r: [2]u64 = ---, ---; - sr: u32 = 0; - - low :: ODIN_ENDIAN == "big" ? 1 : 0; - high :: 1 - low; - U64_BITS :: 8*size_of(u64); - U128_BITS :: 8*size_of(u128); - - // Special Cases - - if n[high] == 0 { - if d[high] == 0 { - if rem != nil { - rem^ = u128(n[low] % d[low]); - } - return u128(n[low] / d[low]); - } - - if rem != nil { - rem^ = u128(n[low]); - } - return 0; - } - - if d[low] == 0 { - if d[high] == 0 { - if rem != nil { - rem^ = u128(n[high] % d[low]); - } - return u128(n[high] / d[low]); - } - if n[low] == 0 { - if rem != nil { - r[high] = n[high] % d[high]; - r[low] = 0; - rem^ = transmute(u128)r; - } - return u128(n[high] / d[high]); - } - - if d[high] & (d[high]-1) == 0 { - if rem != nil { - r[low] = n[low]; - r[high] = n[high] & (d[high] - 1); - rem^ = transmute(u128)r; - } - return u128(n[high] >> _ctz(d[high])); - } - - sr = transmute(u32)(i32(_clz(d[high])) - i32(_clz(n[high]))); - if sr > U64_BITS - 2 { - if rem != nil { - rem^ = a; - } - return 0; - } - - sr += 1; - - q[low] = 0; - q[high] = n[low] << u64(U64_BITS - sr); - r[high] = n[high] >> sr; - r[low] = (n[high] << (U64_BITS - sr)) | (n[low] >> sr); - } else { - if d[high] == 0 { - if d[low] & (d[low] - 1) == 0 { - if rem != nil { - rem^ = u128(n[low] & (d[low] - 1)); - } - if d[low] == 1 { - return a; - } - sr = u32(_ctz(d[low])); - q[high] = n[high] >> sr; - q[low] = (n[high] << (U64_BITS-sr)) | (n[low] >> sr); - return transmute(u128)q; - } - - sr = 1 + U64_BITS + u32(_clz(d[low])) - u32(_clz(n[high])); - - switch { - case sr == U64_BITS: - q[low] = 0; - q[high] = n[low]; - r[high] = 0; - r[low] = n[high]; - case sr < U64_BITS: - q[low] = 0; - q[high] = n[low] << (U64_BITS - sr); - r[high] = n[high] >> sr; - r[low] = (n[high] << (U64_BITS - sr)) | (n[low] >> sr); - case: - q[low] = n[low] << (U128_BITS - sr); - q[high] = (n[high] << (U128_BITS - sr)) | (n[low] >> (sr - U64_BITS)); - r[high] = 0; - r[low] = n[high] >> (sr - U64_BITS); - } - } else { - sr = transmute(u32)(i32(_clz(d[high])) - i32(_clz(n[high]))); - - if sr > U64_BITS - 1 { - if rem != nil { - rem^ = a; - } - return 0; - } - - sr += 1; - - q[low] = 0; - if sr == U64_BITS { - q[high] = n[low]; - r[high] = 0; - r[low] = n[high]; - } else { - r[high] = n[high] >> sr; - r[low] = (n[high] << (U64_BITS - sr)) | (n[low] >> sr); - q[high] = n[low] << (U64_BITS - sr); - } - } - } - - carry: u32 = 0; - r_all: u128 = ---; - - for ; sr > 0; sr -= 1 { - r[high] = (r[high] << 1) | (r[low] >> (U64_BITS - 1)); - r[low] = (r[low] << 1) | (q[high] >> (U64_BITS - 1)); - q[high] = (q[high] << 1) | (q[low] >> (U64_BITS - 1)); - q[low] = (q[low] << 1) | u64(carry); - - r_all = transmute(u128)r; - s := i128(b - r_all - 1) >> (U128_BITS - 1); - carry = u32(s & 1); - r_all -= b & transmute(u128)s; - r = transmute([2]u64)r_all; - } - - q_all := ((transmute(u128)q) << 1) | u128(carry); - if rem != nil { - rem^ = r_all; - } - - return q_all; -} - @(link_name="__umodti3") umodti3 :: proc "c" (a, b: i128) -> i128 { s_a := a >> (128 - 1); diff --git a/core/strconv/generic_float.odin b/core/strconv/generic_float.odin index e4784a2e5..99830ad30 100644 --- a/core/strconv/generic_float.odin +++ b/core/strconv/generic_float.odin @@ -2,13 +2,6 @@ package strconv using import "decimal" -Int_Flag :: enum { - Prefix, - Plus, - Space, -} -Int_Flags :: bit_set[Int_Flag]; - Decimal_Slice :: struct { digits: []byte, count: int, @@ -286,154 +279,3 @@ round_shortest :: proc(d: ^Decimal, mant: u64, exp: int, flt: ^Float_Info) { } } - -MAX_BASE :: 32; -digits := "0123456789abcdefghijklmnopqrstuvwxyz"; - - -is_integer_negative :: proc(x: u64, is_signed: bool, bit_size: int) -> (u: u64, neg: bool) { - u = x; - if is_signed { - switch bit_size { - case 8: - i := i8(u); - neg = i < 0; - u = u64(abs(i64(i))); - case 16: - i := i16(u); - neg = i < 0; - u = u64(abs(i64(i))); - case 32: - i := i32(u); - neg = i < 0; - u = u64(abs(i64(i))); - case 64: - i := i64(u); - neg = i < 0; - u = u64(abs(i64(i))); - case: - panic("is_integer_negative: Unknown integer size"); - } - } - return; -} - -append_bits :: proc(buf: []byte, x: u64, base: int, is_signed: bool, bit_size: int, digits: string, flags: Int_Flags) -> string { - if base < 2 || base > MAX_BASE { - panic("strconv: illegal base passed to append_bits"); - } - - a: [129]byte; - i := len(a); - u, neg := is_integer_negative(x, is_signed, bit_size); - b := u64(base); - for u >= b { - i-=1; a[i] = digits[u % b]; - u /= b; - } - i-=1; a[i] = digits[u % b]; - - if .Prefix in flags { - ok := true; - switch base { - case 2: i-=1; a[i] = 'b'; - case 8: i-=1; a[i] = 'o'; - case 10: i-=1; a[i] = 'd'; - case 12: i-=1; a[i] = 'z'; - case 16: i-=1; a[i] = 'x'; - case: ok = false; - } - if ok { - i-=1; a[i] = '0'; - } - } - - switch { - case neg: - i-=1; a[i] = '-'; - case .Plus in flags: - i-=1; a[i] = '+'; - case .Space in flags: - i-=1; a[i] = ' '; - } - - out := a[i:]; - copy(buf, out); - return string(buf[0:len(out)]); -} - -is_integer_negative_128 :: proc(x: u128, is_signed: bool, bit_size: int) -> (u: u128, neg: bool) { - u = x; - if is_signed { - switch bit_size { - case 8: - i := i8(u); - neg = i < 0; - u = u128(abs(i128(i))); - case 16: - i := i16(u); - neg = i < 0; - u = u128(abs(i128(i))); - case 32: - i := i32(u); - neg = i < 0; - u = u128(abs(i128(i))); - case 64: - i := i64(u); - neg = i < 0; - u = u128(abs(i128(i))); - case 128: - i := i128(u); - neg = i < 0; - u = u128(abs(i128(i))); - case: - panic("is_integer_negative: Unknown integer size"); - } - } - return; -} - - -append_bits_128 :: proc(buf: []byte, x: u128, base: int, is_signed: bool, bit_size: int, digits: string, flags: Int_Flags) -> string { - if base < 2 || base > MAX_BASE { - panic("strconv: illegal base passed to append_bits"); - } - - a: [140]byte; - i := len(a); - u, neg := is_integer_negative_128(x, is_signed, bit_size); - b := u128(base); - for u >= b { - i-=1; a[i] = digits[u % b]; - u /= b; - } - i-=1; a[i] = digits[u % b]; - - if .Prefix in flags { - ok := true; - switch base { - case 2: i-=1; a[i] = 'b'; - case 8: i-=1; a[i] = 'o'; - case 10: i-=1; a[i] = 'd'; - case 12: i-=1; a[i] = 'z'; - case 16: i-=1; a[i] = 'x'; - case: ok = false; - } - if ok { - i-=1; a[i] = '0'; - } - } - - switch { - case neg: - i-=1; a[i] = '-'; - case .Plus in flags: - i-=1; a[i] = '+'; - case .Space in flags: - i-=1; a[i] = ' '; - } - - out := a[i:]; - copy(buf, out); - return string(buf[0:len(out)]); -} diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 865c7e565..4b76106bd 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -102,6 +102,8 @@ struct BuildContext { TargetMetrics metrics; + bool show_help; + String out_filepath; String resource_filepath; String pdb_filepath; diff --git a/src/main.cpp b/src/main.cpp index 3cb33037e..6950f3ecb 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -177,6 +177,9 @@ void usage(String argv0) { print_usage_line(1, "query parse, type check, and output a .json file containing information about the program"); print_usage_line(1, "docs generate documentation for a .odin file"); print_usage_line(1, "version print version"); + print_usage_line(0, ""); + print_usage_line(0, "For more information of flags, apply the flag to see what is possible"); + print_usage_line(1, "-help"); } @@ -213,6 +216,8 @@ bool string_is_valid_identifier(String str) { enum BuildFlagKind { BuildFlag_Invalid, + BuildFlag_Help, + BuildFlag_OutFile, BuildFlag_OptimizationLevel, BuildFlag_ShowTimings, @@ -301,6 +306,7 @@ ExactValue build_param_to_exact_value(String name, String param) { bool parse_build_flags(Array args) { auto build_flags = array_make(heap_allocator(), 0, BuildFlag_COUNT); + add_flag(&build_flags, BuildFlag_Help, str_lit("help"), BuildFlagParam_None); add_flag(&build_flags, BuildFlag_OutFile, str_lit("out"), BuildFlagParam_String); add_flag(&build_flags, BuildFlag_OptimizationLevel, str_lit("opt"), BuildFlagParam_Integer); add_flag(&build_flags, BuildFlag_ShowTimings, str_lit("show-timings"), BuildFlagParam_None); @@ -447,6 +453,10 @@ bool parse_build_flags(Array args) { } if (ok) switch (bf.kind) { + case BuildFlag_Help: + build_context.show_help = true; + break; + case BuildFlag_OutFile: { GB_ASSERT(value.kind == ExactValue_String); String path = value.value_string; @@ -616,7 +626,7 @@ bool parse_build_flags(Array args) { String str = value.value_string; bool found = false; - for (int i = 0; i < sizeof(named_targets) / sizeof(named_targets[0]); i++) { + for (isize i = 0; i < gb_count_of(named_targets); i++) { if (str_eq_ignore_case(str, named_targets[i].name)) { found = true; selected_target_metrics = named_targets + i; @@ -1023,6 +1033,131 @@ int main(int arg_count, char const **arg_ptr) { return 1; } + if (build_context.show_help) { + print_usage_line(0, "%.*s is a tool for managing Odin source code", LIT(args[0])); + print_usage_line(0, "Usage"); + print_usage_line(1, "%.*s %.*s [arguments]", LIT(args[0]), LIT(command)); + print_usage_line(0, ""); + + bool build = command == "build"; + bool run_or_build = command == "run" || command == "build"; + bool check = command == "run" || command == "build" || command == "check"; + + + if (run_or_build) { + print_usage_line(1, "-out:"); + print_usage_line(2, "Set the file name of the outputted executable"); + print_usage_line(2, "Example: -out:foo.exe"); + print_usage_line(0, ""); + + print_usage_line(1, "-opt:"); + print_usage_line(2, "Set the optimization level for complication"); + print_usage_line(2, "Accepted values: 0, 1, 2, 3"); + print_usage_line(2, "Example: -opt:2"); + print_usage_line(0, ""); + } + + if (check) { + print_usage_line(1, "-show-timings"); + print_usage_line(2, "Shows basic overview of the timings of different stages within the compiler in milliseconds"); + print_usage_line(0, ""); + + print_usage_line(1, "-show-more-timings"); + print_usage_line(2, "Shows an advanced overview of the timings of different stages within the compiler in milliseconds"); + print_usage_line(0, ""); + + print_usage_line(1, "-thread-count:"); + print_usage_line(2, "Override the number of threads the compiler will use to compile with"); + print_usage_line(2, "Example: -thread-count:2"); + print_usage_line(0, ""); + } + + if (run_or_build) { + print_usage_line(1, "-keep-temp-files"); + print_usage_line(2, "Keeps the temporary files generated during compilation"); + print_usage_line(0, ""); + } + + if (check) { + print_usage_line(1, "-collection:="); + print_usage_line(2, "Defines a library collection used for imports"); + print_usage_line(2, "Example: -collection:shared:dir/to/shared"); + print_usage_line(2, "Usage in Code:"); + print_usage_line(3, "import \"shared:foo\""); + print_usage_line(0, ""); + + print_usage_line(1, "-define:="); + print_usage_line(2, "Defines a global constant with a value"); + print_usage_line(2, "Example: -define:SPAM=123"); + print_usage_line(0, ""); + } + + if (build) { + print_usage_line(1, "-build-mode:"); + print_usage_line(2, "Sets the build mode"); + print_usage_line(2, "Available options:"); + print_usage_line(3, "-build-mode:exe Build as an executable"); + print_usage_line(3, "-build-mode:dll Build as a dynamically linked library"); + print_usage_line(3, "-build-mode:shared Build as a dynamically linked library"); + print_usage_line(0, ""); + } + + if (check) { + print_usage_line(1, "-target:"); + print_usage_line(2, "Sets the target for the executable to be built in"); + print_usage_line(0, ""); + } + + if (run_or_build) { + print_usage_line(1, "-debug"); + print_usage_line(2, "Enabled debug information, and defines the global constant ODIN_DEBUG to be 'true'"); + print_usage_line(0, ""); + + print_usage_line(1, "-no-bounds-check"); + print_usage_line(2, "Disables bounds checking program wide"); + print_usage_line(0, ""); + + print_usage_line(1, "-no-crt"); + print_usage_line(2, "Disables automatic linking with the C Run Time"); + print_usage_line(0, ""); + + print_usage_line(1, "-use-lld"); + print_usage_line(2, "Use the LLD linker rather than the default"); + print_usage_line(0, ""); + } + + if (check) { + print_usage_line(1, "-vet"); + print_usage_line(2, "Do extra checks on the code"); + print_usage_line(2, "Extra checks include:"); + print_usage_line(3, "Variable shadowing within procedures"); + print_usage_line(3, "Unused declarations"); + print_usage_line(0, ""); + + print_usage_line(1, "-ignore-unknown-attributes"); + print_usage_line(2, "Ignores unknown attributes"); + print_usage_line(2, "This can be used with metaprogramming tools"); + print_usage_line(0, ""); + } + + if (run_or_build) { + #if defined(GB_SYSTEM_WINDOWS) + print_usage_line(1, "-resource:"); + print_usage_line(2, "[Windows only]"); + print_usage_line(2, "Defines the resource file for the executable"); + print_usage_line(2, "Example: -resource:path/to/file.rc"); + print_usage_line(0, ""); + + print_usage_line(1, "-pdb-name:"); + print_usage_line(2, "[Windows only]"); + print_usage_line(2, "Defines the generated PDB name when -debug is enabled"); + print_usage_line(2, "Example: -pdb-name:different.pdb"); + print_usage_line(0, ""); + #endif + } + return 0; + } + // NOTE(bill): add 'shared' directory if it is not already set @@ -1180,7 +1315,7 @@ int main(int arg_count, char const **arg_ptr) { // NOTE(ic): It would be nice to extend this so that we could specify the Visual Studio version that we want instead of defaulting to the latest. Find_Result_Utf8 find_result = find_visual_studio_and_windows_sdk_utf8(); - // defer(free_resources(&find_result)); + // defer(free_"resource"s(&find_result)); if (find_result.windows_sdk_version == 0) { gb_printf_err("Windows SDK not found.\n");