Browse Source

Add comments to `builtin.odin`, documenting ODIN_* constants. (#5218)

And document constants not previously listed.
Jeroen van Rijn 2 months ago
parent
commit
229c734820
5 changed files with 324 additions and 88 deletions
  1. 223 7
      base/builtin/builtin.odin
  2. 68 67
      src/build_settings.cpp
  3. 25 6
      src/checker.cpp
  4. 3 3
      src/linker.cpp
  5. 5 5
      src/main.cpp

+ 223 - 7
base/builtin/builtin.odin

@@ -7,13 +7,226 @@ nil   :: nil
 false :: 0!=0
 true  :: 0==0
 
-ODIN_OS      :: ODIN_OS
-ODIN_ARCH    :: ODIN_ARCH
-ODIN_ENDIAN  :: ODIN_ENDIAN
-ODIN_VENDOR  :: ODIN_VENDOR
-ODIN_VERSION :: ODIN_VERSION
-ODIN_ROOT    :: ODIN_ROOT
-ODIN_DEBUG   :: ODIN_DEBUG
+// The following constants are added in `checker.cpp`'s `init_universal` procedure.
+
+/*
+	An `enum` value indicating what the CPU architecture of the target is.
+	Possible values are: `.amd64`, `.i386`, `.arm32`, `.arm64`, `.wasm32`, `.wasm64p32`, and `.riscv64`.
+*/
+ODIN_ARCH                       :: ODIN_ARCH
+
+/*
+	A `string` indicating what the CPU architecture of the target is.
+	Possible values are: "amd64", "i386", "arm32", "arm64", "wasm32", "wasm64p32", "riscv64".
+*/
+ODIN_ARCH_STRING                :: ODIN_ARCH_STRING
+
+/*
+	An `enum` value indicating the type of compiled output, chosen using `-build-mode`.
+	Possible values are: `.Executable`, `.Dynamic`, `.Static`, `.Object`, `.Assembly`, and `.LLVM_IR`.
+*/
+ODIN_BUILD_MODE                 :: ODIN_BUILD_MODE
+
+/*
+	A `string` containing the name of the folder that contains the entry point,
+	e.g. for `%ODIN_ROOT%/examples/demo`, this would contain `demo`.
+*/
+ODIN_BUILD_PROJECT_NAME         :: ODIN_BUILD_PROJECT_NAME
+
+/*
+	An `i64` containing the time at which the executable was compiled, in nanoseconds.
+	This is compatible with the `time.Time` type, i.e. `time.Time{_nsec=ODIN_COMPILE_TIMESTAMP}`
+*/
+ODIN_COMPILE_TIMESTAMP          :: ODIN_COMPILE_TIMESTAMP
+
+/*
+	`true` if the `-debug` command line switch is passed, which enables debug info generation.
+*/
+ODIN_DEBUG                      :: ODIN_DEBUG
+
+/*
+	`true` if the `-default-to-nil-allocator` command line switch is passed,
+	which sets the initial `context.allocator` to an allocator that does nothing.
+*/
+ODIN_DEFAULT_TO_NIL_ALLOCATOR   :: ODIN_DEFAULT_TO_NIL_ALLOCATOR
+
+/*
+	`true` if the `-default-to-panic-allocator` command line switch is passed,
+	which sets the initial `context.allocator` to an allocator that panics if allocated from.
+*/
+ODIN_DEFAULT_TO_PANIC_ALLOCATOR :: ODIN_DEFAULT_TO_PANIC_ALLOCATOR
+
+/*
+	`true` if the `-disable-assert` command line switch is passed,
+	which removes all calls to `assert` from the program.
+*/
+ODIN_DISABLE_ASSERT             :: ODIN_DISABLE_ASSERT
+
+/*
+	An `enum` value indicating the endianness of the target.
+	Possible values are: `.Little` and `.Big`.
+*/
+ODIN_ENDIAN                     :: ODIN_ENDIAN
+
+/*
+	An `enum` value indicating the endianness of the target.
+	Possible values are: "little" and "big".
+*/
+ODIN_ENDIAN_STRING              :: ODIN_ENDIAN_STRING
+
+/*
+	An `enum` value set using the `-error-pos-style` switch, indicating the source location style used for compile errors and warnings.
+	Possible values are: `.Default` (Odin-style) and `.Unix`.
+*/
+ODIN_ERROR_POS_STYLE            :: ODIN_ERROR_POS_STYLE
+
+/*
+	`true` if the `-foreign-error-procedures` command line switch is passed,
+	which inhibits generation of runtime error procedures, so that they can be in a separate compilation unit.
+*/
+ODIN_FOREIGN_ERROR_PROCEDURES   :: ODIN_FOREIGN_ERROR_PROCEDURES
+
+/*
+	A `string` describing the microarchitecture used for code generation.
+	If not set using the `-microarch` command line switch, the compiler will pick a default.
+	Possible values include, but are not limited to: "sandybridge", "x86-64-v2".
+*/
+ODIN_MICROARCH_STRING           :: ODIN_MICROARCH_STRING
+
+/*
+	An `int` value representing the minimum OS version given to the linker, calculated as `major * 10_000 + minor * 100 + revision`.
+	If not set using the `-minimum-os-version` command line switch, it defaults to `0`.
+*/
+ODIN_MINIMUM_OS_VERSION         :: ODIN_MINIMUM_OS_VERSION
+
+/*
+	`true` if the `-no-bounds-check` command line switch is passed, which disables bounds checking at runtime.
+*/
+ODIN_NO_BOUNDS_CHECK            :: ODIN_NO_BOUNDS_CHECK
+
+/*
+	`true` if the `-no-crt` command line switch is passed, which inhibits linking with the C Runtime Library, a.k.a. LibC.
+*/
+ODIN_NO_CRT                     :: ODIN_NO_CRT
+
+/*
+	`true` if the `-no-entry-point` command line switch is passed, which makes the declaration of a `main` procedure optional.
+*/
+ODIN_NO_ENTRY_POINT             :: ODIN_NO_ENTRY_POINT
+
+/*
+	`true` if the `-no-rtti` command line switch is passed, which inhibits generation of full Runtime Type Information.
+*/
+ODIN_NO_RTTI                    :: ODIN_NO_RTTI
+
+/*
+	`true` if the `-no-type-assert` command line switch is passed, which disables type assertion checking program wide.
+*/
+ODIN_NO_TYPE_ASSERT             :: ODIN_NO_TYPE_ASSERT
+
+/*
+	An `enum` value indicating the optimization level selected using the `-o` command line switch.
+	Possible values are: `.None`, `.Minimal`, `.Size`, `.Speed`, and `.Aggressive`.
+*/
+ODIN_OPTIMIZATION_MODE          :: ODIN_OPTIMIZATION_MODE
+
+/*
+	An `enum` value indicating what the target operating system is.
+*/
+ODIN_OS                         :: ODIN_OS
+
+/*
+	A `string` indicating what the target operating system is.
+*/
+ODIN_OS_STRING                  :: ODIN_OS_STRING
+
+/*
+	An `enum` value indicating the platform subtarget, chosen using the `-subtarget` switch.
+	Possible values are: `.Default` `.iOS`, and `.Android`.
+*/
+ODIN_PLATFORM_SUBTARGET         :: ODIN_PLATFORM_SUBTARGET
+
+/*
+	A `string` representing the path of the folder containing the Odin compiler,
+	relative to which we expect to find the `base` and `core` package collections.
+*/
+ODIN_ROOT                       :: ODIN_ROOT
+
+/*
+	A `bit_set` indicating the sanitizer flags set using the `-sanitize` command line switch.
+	Supported flags are `.Address`, `.Memory`, and `.Thread`.
+*/
+ODIN_SANITIZER_FLAGS            :: ODIN_SANITIZER_FLAGS
+
+/*
+	`true` if the code is being compiled via an invocation of `odin test`.
+*/
+ODIN_TEST                       :: ODIN_TEST
+
+/*
+	`true` if built using the experimental Tilde backend.
+*/
+ODIN_TILDE                      :: ODIN_TILDE
+
+/*
+	`true` if the `-use-separate-modules` command line switch is passed,
+	which builds each package into its own object file, and then links them together, instead of performing a unity build.
+*/
+ODIN_USE_SEPARATE_MODULES       :: ODIN_USE_SEPARATE_MODULES
+
+/*
+	`true` if Valgrind integration is supported on the target.
+*/
+ODIN_VALGRIND_SUPPORT           :: ODIN_VALGRIND_SUPPORT
+
+/*
+	A `string` which identifies the compiler being used. The official compiler sets this to `"odin"`.
+*/
+ODIN_VENDOR                     :: ODIN_VENDOR
+
+/*
+	A `string` containing the version of the Odin compiler, typically in the format `dev-YYYY-MM`.
+*/
+ODIN_VERSION                    :: ODIN_VERSION
+
+/*
+	A `string` containing the Git hash part of the Odin version.
+	Empty if `.git` could not be detected at the time the compiler was built.
+*/
+ODIN_VERSION_HASH               :: ODIN_VERSION_HASH
+
+/*
+	An `enum` set by the `-subsystem` flag, specifying which Windows subsystem the PE file was created for.
+	Possible values are:
+		`.Unknown` - Default and only value on non-Windows platforms
+		`.Console` - Default on Windows
+		`.Windows` - Can be used by graphical applications so Windows doesn't open an empty console
+
+	There are some other possible values for e.g. EFI applications, but only Console and Windows are supported.
+
+	See also: https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-image_optional_header64
+*/
+ODIN_WINDOWS_SUBSYSTEM          :: ODIN_WINDOWS_SUBSYSTEM
+
+/*
+	An `string` set by the `-subsystem` flag, specifying which Windows subsystem the PE file was created for.
+	Possible values are:
+		"UNKNOWN" - Default and only value on non-Windows platforms
+		"CONSOLE" - Default on Windows
+		"WINDOWS" - Can be used by graphical applications so Windows doesn't open an empty console
+
+	There are some other possible values for e.g. EFI applications, but only Console and Windows are supported.
+
+	See also: https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-image_optional_header64
+*/
+ODIN_WINDOWS_SUBSYSTEM_STRING   :: ODIN_WINDOWS_SUBSYSTEM_STRING
+
+/*
+	`true` if LLVM supports the f16 type.
+*/
+__ODIN_LLVM_F16_SUPPORTED       :: __ODIN_LLVM_F16_SUPPORTED
+
+
 
 byte :: u8 // alias
 
@@ -131,3 +344,6 @@ soa_zip :: proc(slices: ...) -> #soa[]Struct ---
 soa_unzip :: proc(value: $S/#soa[]$E) -> (slices: ...) ---
 
 unreachable :: proc() -> ! ---
+
+// Where T is a string, slice, dynamic array, or pointer to an array type
+raw_data :: proc(t: $T) -> rawptr

+ 68 - 67
src/build_settings.cpp

@@ -31,6 +31,24 @@ enum TargetOsKind : u16 {
 	TargetOs_COUNT,
 };
 
+gb_global String target_os_names[TargetOs_COUNT] = {
+	str_lit(""),
+	str_lit("windows"),
+	str_lit("darwin"),
+	str_lit("linux"),
+	str_lit("essence"),
+	str_lit("freebsd"),
+	str_lit("openbsd"),
+	str_lit("netbsd"),
+	str_lit("haiku"),
+
+	str_lit("wasi"),
+	str_lit("js"),
+	str_lit("orca"),
+
+	str_lit("freestanding"),
+};
+
 enum TargetArchKind : u16 {
 	TargetArch_Invalid,
 
@@ -45,6 +63,17 @@ enum TargetArchKind : u16 {
 	TargetArch_COUNT,
 };
 
+gb_global String target_arch_names[TargetArch_COUNT] = {
+	str_lit(""),
+	str_lit("amd64"),
+	str_lit("i386"),
+	str_lit("arm32"),
+	str_lit("arm64"),
+	str_lit("wasm32"),
+	str_lit("wasm64p32"),
+	str_lit("riscv64"),
+};
+
 enum TargetEndianKind : u8 {
 	TargetEndian_Little,
 	TargetEndian_Big,
@@ -52,6 +81,11 @@ enum TargetEndianKind : u8 {
 	TargetEndian_COUNT,
 };
 
+gb_global String target_endian_names[TargetEndian_COUNT] = {
+	str_lit("little"),
+	str_lit("big"),
+};
+
 enum TargetABIKind : u16 {
 	TargetABI_Default,
 
@@ -61,7 +95,14 @@ enum TargetABIKind : u16 {
 	TargetABI_COUNT,
 };
 
+gb_global String target_abi_names[TargetABI_COUNT] = {
+	str_lit(""),
+	str_lit("win64"),
+	str_lit("sysv"),
+};
+
 enum Windows_Subsystem : u8 {
+	Windows_Subsystem_UNKNOWN,
  	Windows_Subsystem_BOOT_APPLICATION,
 	Windows_Subsystem_CONSOLE,                 // Default,
 	Windows_Subsystem_EFI_APPLICATION,
@@ -75,38 +116,23 @@ enum Windows_Subsystem : u8 {
 	Windows_Subsystem_COUNT,
 };
 
-struct MicroarchFeatureList {
-	String microarch;
-	String features;
-};
-
-gb_global String target_os_names[TargetOs_COUNT] = {
+gb_global String windows_subsystem_names[Windows_Subsystem_COUNT] = {
 	str_lit(""),
-	str_lit("windows"),
-	str_lit("darwin"),
-	str_lit("linux"),
-	str_lit("essence"),
-	str_lit("freebsd"),
-	str_lit("openbsd"),
-	str_lit("netbsd"),
-	str_lit("haiku"),
-	
-	str_lit("wasi"),
-	str_lit("js"),
-	str_lit("orca"),
-
-	str_lit("freestanding"),
+	str_lit("BOOT_APPLICATION"),
+	str_lit("CONSOLE"), // Default
+	str_lit("EFI_APPLICATION"),
+	str_lit("EFI_BOOT_SERVICE_DRIVER"),
+	str_lit("EFI_ROM"),
+	str_lit("EFI_RUNTIME_DRIVER"),
+	str_lit("NATIVE"),
+	str_lit("POSIX"),
+	str_lit("WINDOWS"),
+	str_lit("WINDOWSCE"),
 };
 
-gb_global String target_arch_names[TargetArch_COUNT] = {
-	str_lit(""),
-	str_lit("amd64"),
-	str_lit("i386"),
-	str_lit("arm32"),
-	str_lit("arm64"),
-	str_lit("wasm32"),
-	str_lit("wasm64p32"),
-	str_lit("riscv64"),
+struct MicroarchFeatureList {
+	String microarch;
+	String features;
 };
 
 #if defined(GB_SYSTEM_WINDOWS)
@@ -114,20 +140,8 @@ gb_global String target_arch_names[TargetArch_COUNT] = {
 #else
 	#include <llvm/Config/llvm-config.h>
 #endif
-
 #include "build_settings_microarch.cpp"
 
-gb_global String target_endian_names[TargetEndian_COUNT] = {
-	str_lit("little"),
-	str_lit("big"),
-};
-
-gb_global String target_abi_names[TargetABI_COUNT] = {
-	str_lit(""),
-	str_lit("win64"),
-	str_lit("sysv"),
-};
-
 gb_global TargetEndianKind target_endians[TargetArch_COUNT] = {
 	TargetEndian_Little,
 	TargetEndian_Little,
@@ -138,19 +152,6 @@ gb_global TargetEndianKind target_endians[TargetArch_COUNT] = {
 	TargetEndian_Little,
 };
 
-gb_global String windows_subsystem_names[Windows_Subsystem_COUNT] = {
-	str_lit("BOOT_APPLICATION"),
-	str_lit("CONSOLE"),                 // Default
-	str_lit("EFI_APPLICATION"),
-	str_lit("EFI_BOOT_SERVICE_DRIVER"),
-	str_lit("EFI_ROM"),
-	str_lit("EFI_RUNTIME_DRIVER"),
-	str_lit("NATIVE"),
-	str_lit("POSIX"),
-	str_lit("WINDOWS"),
-	str_lit("WINDOWSCE"),
-};
-
 #ifndef ODIN_VERSION_RAW
 #define ODIN_VERSION_RAW "dev-unknown-unknown"
 #endif
@@ -393,17 +394,17 @@ String linker_choices[Linker_COUNT] = {
 // This stores the information for the specify architecture of this build
 struct BuildContext {
 	// Constants
-	String ODIN_OS;                       // Target operating system
-	String ODIN_ARCH;                     // Target architecture
-	String ODIN_VENDOR;                   // Compiler vendor
-	String ODIN_VERSION;                  // Compiler version
-	String ODIN_ROOT;                     // Odin ROOT
-	String ODIN_BUILD_PROJECT_NAME;       // Odin main/initial package's directory name
-	String ODIN_WINDOWS_SUBSYSTEM;        // Empty string for non-Windows targets
-	bool   ODIN_DEBUG;                    // Odin in debug mode
-	bool   ODIN_DISABLE_ASSERT;           // Whether the default 'assert' et al is disabled in code or not
-	bool   ODIN_DEFAULT_TO_NIL_ALLOCATOR; // Whether the default allocator is a "nil" allocator or not (i.e. it does nothing)
-	bool   ODIN_DEFAULT_TO_PANIC_ALLOCATOR; // Whether the default allocator is a "panic" allocator or not (i.e. panics on any call to it)
+	String ODIN_OS;                           // Target operating system
+	String ODIN_ARCH;                         // Target architecture
+	String ODIN_VENDOR;                       // Compiler vendor
+	String ODIN_VERSION;                      // Compiler version
+	String ODIN_ROOT;                         // Odin ROOT
+	String ODIN_BUILD_PROJECT_NAME;           // Odin main/initial package's directory name
+	Windows_Subsystem ODIN_WINDOWS_SUBSYSTEM; // .Console, .Windows
+	bool   ODIN_DEBUG;                        // Odin in debug mode
+	bool   ODIN_DISABLE_ASSERT;               // Whether the default 'assert' et al is disabled in code or not
+	bool   ODIN_DEFAULT_TO_NIL_ALLOCATOR;     // Whether the default allocator is a "nil" allocator or not (i.e. it does nothing)
+	bool   ODIN_DEFAULT_TO_PANIC_ALLOCATOR;   // Whether the default allocator is a "panic" allocator or not (i.e. panics on any call to it)
 	bool   ODIN_FOREIGN_ERROR_PROCEDURES;
 	bool   ODIN_VALGRIND_SUPPORT;
 
@@ -1788,8 +1789,8 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta
 	}
 
 	// Default to subsystem:CONSOLE on Windows targets
-	if (bc->ODIN_WINDOWS_SUBSYSTEM == "" && bc->metrics.os == TargetOs_windows) {
-		bc->ODIN_WINDOWS_SUBSYSTEM = windows_subsystem_names[Windows_Subsystem_CONSOLE];
+	if (bc->ODIN_WINDOWS_SUBSYSTEM == Windows_Subsystem_UNKNOWN && bc->metrics.os == TargetOs_windows) {
+		bc->ODIN_WINDOWS_SUBSYSTEM = Windows_Subsystem_CONSOLE;
 	}
 
 	if (subtarget == Subtarget_Android) {

+ 25 - 6
src/checker.cpp

@@ -1078,11 +1078,30 @@ gb_internal void init_universal(void) {
 	add_global_bool_constant("true",  true);
 	add_global_bool_constant("false", false);
 
-	add_global_string_constant("ODIN_VENDOR",             bc->ODIN_VENDOR);
-	add_global_string_constant("ODIN_VERSION",            bc->ODIN_VERSION);
-	add_global_string_constant("ODIN_ROOT",               bc->ODIN_ROOT);
-	add_global_string_constant("ODIN_BUILD_PROJECT_NAME", bc->ODIN_BUILD_PROJECT_NAME);
-	add_global_string_constant("ODIN_WINDOWS_SUBSYSTEM",  bc->ODIN_WINDOWS_SUBSYSTEM);
+	add_global_string_constant("ODIN_VENDOR",                   bc->ODIN_VENDOR);
+	add_global_string_constant("ODIN_VERSION",                  bc->ODIN_VERSION);
+	add_global_string_constant("ODIN_ROOT",                     bc->ODIN_ROOT);
+	add_global_string_constant("ODIN_BUILD_PROJECT_NAME",       bc->ODIN_BUILD_PROJECT_NAME);
+
+	{
+		GlobalEnumValue values[Windows_Subsystem_COUNT] = {
+			{"Unknown",                 Windows_Subsystem_UNKNOWN},
+		 	{"Boot_Application",        Windows_Subsystem_BOOT_APPLICATION},
+			{"Console",                 Windows_Subsystem_CONSOLE},
+			{"EFI_Application",         Windows_Subsystem_EFI_APPLICATION},
+			{"EFI_Boot_Service_Driver", Windows_Subsystem_EFI_BOOT_SERVICE_DRIVER},
+			{"EFI_Rom",                 Windows_Subsystem_EFI_ROM},
+			{"EFI_Runtime_Driver",      Windows_Subsystem_EFI_RUNTIME_DRIVER},
+			{"Native",                  Windows_Subsystem_NATIVE},
+			{"Posix",                   Windows_Subsystem_POSIX},
+			{"Windows",                 Windows_Subsystem_WINDOWS},
+			{"Windows_CE",              Windows_Subsystem_WINDOWSCE},
+		};
+
+		auto fields = add_global_enum_type(str_lit("Odin_Windows_Subsystem_Type"), values, gb_count_of(values));
+		add_global_enum_constant(fields, "ODIN_WINDOWS_SUBSYSTEM",  bc->ODIN_WINDOWS_SUBSYSTEM);
+		add_global_string_constant("ODIN_WINDOWS_SUBSYSTEM_STRING", windows_subsystem_names[bc->ODIN_WINDOWS_SUBSYSTEM]);
+	}
 
 	{
 		GlobalEnumValue values[TargetOs_COUNT] = {
@@ -1102,7 +1121,7 @@ gb_internal void init_universal(void) {
 		};
 
 		auto fields = add_global_enum_type(str_lit("Odin_OS_Type"), values, gb_count_of(values));
-		add_global_enum_constant(fields, "ODIN_OS", bc->metrics.os);
+		add_global_enum_constant(fields, "ODIN_OS",  bc->metrics.os);
 		add_global_string_constant("ODIN_OS_STRING", target_os_names[bc->metrics.os]);
 	}
 

+ 3 - 3
src/linker.cpp

@@ -321,7 +321,7 @@ try_cross_linking:;
 					"",
 					LIT(build_context.ODIN_ROOT), object_files, LIT(output_filename),
 					link_settings,
-					LIT(build_context.ODIN_WINDOWS_SUBSYSTEM),
+					LIT(windows_subsystem_names[build_context.ODIN_WINDOWS_SUBSYSTEM]),
 					LIT(build_context.link_flags),
 					LIT(build_context.extra_linker_flags),
 					lib_str
@@ -341,7 +341,7 @@ try_cross_linking:;
 					"",
 					LIT(build_context.ODIN_ROOT), object_files, LIT(output_filename),
 					link_settings,
-					LIT(build_context.ODIN_WINDOWS_SUBSYSTEM),
+					LIT(windows_subsystem_names[build_context.ODIN_WINDOWS_SUBSYSTEM]),
 					LIT(build_context.link_flags),
 					LIT(build_context.extra_linker_flags),
 					lib_str
@@ -404,7 +404,7 @@ try_cross_linking:;
 					"",
 					LIT(vs_exe_path), LIT(linker_name), object_files, LIT(res_path), LIT(output_filename),
 					link_settings,
-					LIT(build_context.ODIN_WINDOWS_SUBSYSTEM),
+					LIT(windows_subsystem_names[build_context.ODIN_WINDOWS_SUBSYSTEM]),
 					LIT(build_context.link_flags),
 					LIT(build_context.extra_linker_flags),
 					lib_str

+ 5 - 5
src/main.cpp

@@ -1627,9 +1627,9 @@ gb_internal bool parse_build_flags(Array<String> args) {
 							GB_ASSERT(value.kind == ExactValue_String);
 							String subsystem = value.value_string;
 							bool subsystem_found = false;
-							for (int i = 0; i < Windows_Subsystem_COUNT; i++) {
+							for (int i = 1; i < Windows_Subsystem_COUNT; i++) {
 								if (str_eq_ignore_case(subsystem, windows_subsystem_names[i])) {
-									build_context.ODIN_WINDOWS_SUBSYSTEM = windows_subsystem_names[i];
+									build_context.ODIN_WINDOWS_SUBSYSTEM = Windows_Subsystem(i);
 									subsystem_found = true;
 									break;
 								}
@@ -1638,7 +1638,7 @@ gb_internal bool parse_build_flags(Array<String> args) {
 							// WINDOW is a hidden alias for WINDOWS. Check it.
 							String subsystem_windows_alias = str_lit("WINDOW");
 							if (!subsystem_found && str_eq_ignore_case(subsystem, subsystem_windows_alias)) {
-								build_context.ODIN_WINDOWS_SUBSYSTEM = windows_subsystem_names[Windows_Subsystem_WINDOWS];
+								build_context.ODIN_WINDOWS_SUBSYSTEM = Windows_Subsystem_WINDOWS;
 								subsystem_found = true;
 								break;
 							}
@@ -1646,8 +1646,8 @@ gb_internal bool parse_build_flags(Array<String> args) {
 							if (!subsystem_found) {
 								gb_printf_err("Invalid -subsystem string, got %.*s. Expected one of:\n", LIT(subsystem));
 								gb_printf_err("\t");
-								for (int i = 0; i < Windows_Subsystem_COUNT; i++) {
-									if (i > 0) {
+								for (int i = 1; i < Windows_Subsystem_COUNT; i++) {
+									if (i > 1) {
 										gb_printf_err(", ");
 									}
 									gb_printf_err("%.*s", LIT(windows_subsystem_names[i]));