mirror of
https://github.com/odin-lang/Odin.git
synced 2025-12-29 17:34:34 +00:00
Add -help which prints information about the compiler flags
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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)]);
|
||||
}
|
||||
|
||||
@@ -102,6 +102,8 @@ struct BuildContext {
|
||||
|
||||
TargetMetrics metrics;
|
||||
|
||||
bool show_help;
|
||||
|
||||
String out_filepath;
|
||||
String resource_filepath;
|
||||
String pdb_filepath;
|
||||
|
||||
139
src/main.cpp
139
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<String> args) {
|
||||
auto build_flags = array_make<BuildFlag>(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<String> 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<String> 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:<filepath>");
|
||||
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:<integer>");
|
||||
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:<integer>");
|
||||
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:<name>=<filepath>");
|
||||
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:<name>=<expression>");
|
||||
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:<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:<string>");
|
||||
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:<filepath>");
|
||||
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:<filepath>");
|
||||
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");
|
||||
|
||||
Reference in New Issue
Block a user