Merge tag 'dev-2025-06'

This commit is contained in:
ed
2025-06-07 11:48:16 -04:00
82 changed files with 3302 additions and 1597 deletions
+132 -86
View File
@@ -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,59 +116,32 @@ enum Windows_Subsystem : u8 {
Windows_Subsystem_COUNT,
};
gb_global String windows_subsystem_names[Windows_Subsystem_COUNT] = {
str_lit(""),
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"),
};
struct MicroarchFeatureList {
String microarch;
String features;
};
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"),
};
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"),
};
#if defined(GB_SYSTEM_WINDOWS)
#include <llvm-c/Config/llvm-config.h>
#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
@@ -287,7 +288,7 @@ enum BuildPath : u8 {
BuildPath_VS_LIB, // vs_library_path
BuildPath_Output, // Output Path for .exe, .dll, .so, etc. Can be overridden with `-out:`.
BuildPath_PDB, // Output Path for .pdb file, can be overridden with `-pdb-name:`.
BuildPath_Symbols, // Output Path for .pdb or .dSym file, can be overridden with `-pdb-name:`.
BuildPathCOUNT,
};
@@ -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;
@@ -441,6 +442,7 @@ struct BuildContext {
String extra_assembler_flags;
String microarch;
BuildModeKind build_mode;
bool keep_executable;
bool generate_docs;
bool custom_optimization_level;
i32 optimization_level;
@@ -1787,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) {
@@ -2021,6 +2023,39 @@ gb_internal bool check_target_feature_is_superset_of(String const &superset, Str
return true;
}
gb_internal String infer_object_extension_from_build_context() {
String output_extension = {};
if (is_arch_wasm()) {
output_extension = STR_LIT("wasm.o");
} else {
switch (build_context.metrics.os) {
case TargetOs_windows:
output_extension = STR_LIT("obj");
break;
default:
case TargetOs_darwin:
case TargetOs_linux:
case TargetOs_essence:
output_extension = STR_LIT("o");
break;
case TargetOs_freestanding:
switch (build_context.metrics.abi) {
default:
case TargetABI_Default:
case TargetABI_SysV:
output_extension = STR_LIT("o");
break;
case TargetABI_Win64:
output_extension = STR_LIT("obj");
break;
}
break;
}
}
return output_extension;
}
// NOTE(Jeroen): Set/create the output and other paths and report an error as appropriate.
// We've previously called `parse_build_flags`, so `out_filepath` should be set.
gb_internal bool init_build_paths(String init_filename) {
@@ -2064,10 +2099,6 @@ gb_internal bool init_build_paths(String init_filename) {
}
}
if (bc->pdb_filepath.len > 0) {
bc->build_paths[BuildPath_PDB] = path_from_string(ha, bc->pdb_filepath);
}
if ((bc->command_kind & Command__does_build) && (!bc->ignore_microsoft_magic)) {
// 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 find_result = find_visual_studio_and_windows_sdk();
@@ -2157,13 +2188,8 @@ gb_internal bool init_build_paths(String init_filename) {
if (build_context.metrics.os == TargetOs_windows) {
output_extension = STR_LIT("lib");
}
}else if (build_context.build_mode == BuildMode_Object) {
// By default use a .o object extension.
output_extension = STR_LIT("o");
if (build_context.metrics.os == TargetOs_windows) {
output_extension = STR_LIT("obj");
}
} else if (build_context.build_mode == BuildMode_Object) {
output_extension = infer_object_extension_from_build_context();
} else if (build_context.build_mode == BuildMode_Assembly) {
// By default use a .S asm extension.
output_extension = STR_LIT("S");
@@ -2183,7 +2209,7 @@ gb_internal bool init_build_paths(String init_filename) {
return false;
} else if (bc->build_paths[BuildPath_Output].ext.len == 0) {
gb_printf_err("Output path %.*s must have an appropriate extension.\n", LIT(output_file));
return false;
return false;
}
}
} else {
@@ -2266,6 +2292,26 @@ gb_internal bool init_build_paths(String init_filename) {
bc->build_paths[BuildPath_Output] = output_path;
}
if (build_context.ODIN_DEBUG) {
if (build_context.metrics.os == TargetOs_windows) {
if (bc->pdb_filepath.len > 0) {
bc->build_paths[BuildPath_Symbols] = path_from_string(ha, bc->pdb_filepath);
} else {
Path symbol_path;
symbol_path.basename = copy_string(ha, bc->build_paths[BuildPath_Output].basename);
symbol_path.name = copy_string(ha, bc->build_paths[BuildPath_Output].name);
symbol_path.ext = copy_string(ha, STR_LIT("pdb"));
bc->build_paths[BuildPath_Symbols] = symbol_path;
}
} else if (build_context.metrics.os == TargetOs_darwin) {
Path symbol_path;
symbol_path.basename = copy_string(ha, bc->build_paths[BuildPath_Output].basename);
symbol_path.name = copy_string(ha, bc->build_paths[BuildPath_Output].name);
symbol_path.ext = copy_string(ha, STR_LIT("dSYM"));
bc->build_paths[BuildPath_Symbols] = symbol_path;
}
}
// Do we have an extension? We might not if the output filename was supplied.
if (bc->build_paths[BuildPath_Output].ext.len == 0) {
if (build_context.metrics.os == TargetOs_windows || is_arch_wasm() || build_context.build_mode != BuildMode_Executable) {
@@ -2301,9 +2347,10 @@ gb_internal bool init_build_paths(String init_filename) {
case TargetOs_windows:
case TargetOs_linux:
case TargetOs_darwin:
case TargetOs_freebsd:
break;
default:
gb_printf_err("-sanitize:address is only supported on windows, linux, and darwin\n");
gb_printf_err("-sanitize:address is only supported on Windows, Linux, Darwin, and FreeBSD\n");
return false;
}
}
@@ -2311,12 +2358,10 @@ gb_internal bool init_build_paths(String init_filename) {
if (build_context.sanitizer_flags & SanitizerFlag_Memory) {
switch (build_context.metrics.os) {
case TargetOs_linux:
case TargetOs_freebsd:
break;
default:
gb_printf_err("-sanitize:memory is only supported on linux\n");
return false;
}
if (build_context.metrics.os != TargetOs_linux) {
gb_printf_err("-sanitize:memory is only supported on Linux and FreeBSD\n");
return false;
}
}
@@ -2325,9 +2370,10 @@ gb_internal bool init_build_paths(String init_filename) {
switch (build_context.metrics.os) {
case TargetOs_linux:
case TargetOs_darwin:
case TargetOs_freebsd:
break;
default:
gb_printf_err("-sanitize:thread is only supported on linux and darwin\n");
gb_printf_err("-sanitize:thread is only supported on Linux, Darwin, and FreeBSD\n");
return false;
}
}
+14 -11
View File
@@ -2885,8 +2885,6 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As
// quaternion :: proc(imag, jmag, kmag, real: float_type) -> complex_type
Operand xyzw[4] = {};
u32 first_index = 0;
// NOTE(bill): Invalid will be the default till fixed
operand->type = t_invalid;
operand->mode = Addressing_Invalid;
@@ -2931,6 +2929,7 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As
if (fields_set[*index]) {
error(field->field, "Previously assigned field: '%.*s'", LIT(name));
return false;
}
fields_set[*index] = style;
@@ -2947,7 +2946,6 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As
if (!ok || index < 0) {
return false;
}
first_index = cast(u32)index;
*refs[index] = o;
}
@@ -2972,12 +2970,17 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As
}
for (u32 i = 0; i < 4; i++ ){
u32 j = (i + first_index) % 4;
if (j == first_index) {
convert_to_typed(c, &xyzw[j], xyzw[(first_index+1)%4].type); if (xyzw[j].mode == Addressing_Invalid) return false;
} else {
convert_to_typed(c, &xyzw[j], xyzw[first_index].type); if (xyzw[j].mode == Addressing_Invalid) return false;
// The first typed value found, if any exist, will dictate the type for all untyped values.
for (u32 i = 0; i < 4; i++) {
if (is_type_typed(xyzw[i].type)) {
for (u32 j = 0; j < 4; j++) {
// `convert_to_typed` should check if it is typed already.
convert_to_typed(c, &xyzw[j], xyzw[i].type);
if (xyzw[j].mode == Addressing_Invalid) {
return false;
}
}
break;
}
}
if (xyzw[0].mode == Addressing_Constant &&
@@ -3001,7 +3004,7 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As
gbString ty = type_to_string(xyzw[1].type);
gbString tz = type_to_string(xyzw[2].type);
gbString tw = type_to_string(xyzw[3].type);
error(call, "Mismatched types to 'quaternion', 'x=%s' vs 'y=%s' vs 'z=%s' vs 'w=%s'", tx, ty, tz, tw);
error(call, "Mismatched types to 'quaternion', 'w=%s' vs 'x=%s' vs 'y=%s' vs 'z=%s'", tw, tx, ty, tz);
gb_string_free(tw);
gb_string_free(tz);
gb_string_free(ty);
@@ -3037,7 +3040,7 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As
operand->mode = Addressing_Constant;
}
BasicKind kind = core_type(xyzw[first_index].type)->Basic.kind;
BasicKind kind = core_type(xyzw[0].type)->Basic.kind;
switch (kind) {
case Basic_f16: operand->type = t_quaternion64; break;
case Basic_f32: operand->type = t_quaternion128; break;
+23 -1
View File
@@ -7962,7 +7962,27 @@ gb_internal ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *c
default:
{
gbString str = type_to_string(t);
error(call, "Too many arguments in conversion to '%s'", str);
if (t->kind == Type_Basic) {
ERROR_BLOCK();
switch (t->Basic.kind) {
case Basic_complex32:
case Basic_complex64:
case Basic_complex128:
error(call, "Too many arguments in conversion to '%s'", str);
error_line("\tSuggestion: %s(1+2i) or construct with 'complex'\n", str);
break;
case Basic_quaternion64:
case Basic_quaternion128:
case Basic_quaternion256:
error(call, "Too many arguments in conversion to '%s'", str);
error_line("\tSuggestion: %s(1+2i+3j+4k) or construct with 'quaternion'\n", str);
break;
default:
error(call, "Too many arguments in conversion to '%s'", str);
}
} else {
error(call, "Too many arguments in conversion to '%s'", str);
}
gb_string_free(str);
} break;
case 1: {
@@ -8078,7 +8098,9 @@ gb_internal ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *c
if (pt->kind == Type_Proc && pt->Proc.calling_convention == ProcCC_Odin) {
if ((c->scope->flags & ScopeFlag_ContextDefined) == 0) {
ERROR_BLOCK();
error(call, "'context' has not been defined within this scope, but is required for this procedure call");
error_line("\tSuggestion: 'context = runtime.default_context()'");
}
}
+1
View File
@@ -2855,6 +2855,7 @@ gb_internal void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags)
case Ast_BlockStmt:
case Ast_IfStmt:
case Ast_SwitchStmt:
case Ast_TypeSwitchStmt:
if (token.kind != Token_break) {
error(bs->label, "Label '%.*s' can only be used with 'break'", LIT(e->token.string));
}
+6 -2
View File
@@ -3805,7 +3805,11 @@ gb_internal Type *check_type_expr(CheckerContext *ctx, Ast *e, Type *named_type)
#if 0
error(e, "Invalid type definition of '%.*s'", LIT(type->Named.name));
#endif
type->Named.base = t_invalid;
if (type->Named.type_name->TypeName.is_type_alias) {
// NOTE(laytan): keep it null, type declaration is a mini "cycle" to be filled later.
} else {
type->Named.base = t_invalid;
}
}
if (is_type_polymorphic(type)) {
@@ -3823,7 +3827,7 @@ gb_internal Type *check_type_expr(CheckerContext *ctx, Ast *e, Type *named_type)
}
#endif
if (is_type_typed(type)) {
if (type->kind == Type_Named && type->Named.base == nullptr || is_type_typed(type)) {
add_type_and_value(ctx, e, Addressing_Type, type, empty_exact_value);
} else {
gbString name = type_to_string(type);
+25 -6
View File
@@ -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]);
}
+18 -6
View File
@@ -281,9 +281,9 @@ try_cross_linking:;
link_settings = gb_string_append_fmt(link_settings, " /ENTRY:mainCRTStartup");
}
if (build_context.pdb_filepath != "") {
String pdb_path = path_to_string(heap_allocator(), build_context.build_paths[BuildPath_PDB]);
link_settings = gb_string_append_fmt(link_settings, " /PDB:\"%.*s\"", LIT(pdb_path));
if (build_context.build_paths[BuildPath_Symbols].name != "") {
String symbol_path = path_to_string(heap_allocator(), build_context.build_paths[BuildPath_Symbols]);
link_settings = gb_string_append_fmt(link_settings, " /PDB:\"%.*s\"", LIT(symbol_path));
}
if (build_context.build_mode != BuildMode_StaticLibrary) {
@@ -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
@@ -802,6 +802,18 @@ try_cross_linking:;
link_settings = gb_string_appendc(link_settings, "-e _main ");
}
} else if (build_context.metrics.os == TargetOs_freebsd) {
if (build_context.sanitizer_flags & (SanitizerFlag_Address | SanitizerFlag_Memory)) {
// It's imperative that `pthread` is linked before `libc`,
// otherwise ASan/MSan will be unable to call `pthread_key_create`
// because FreeBSD's `libthr` implementation of `pthread`
// needs to replace the relevant stubs first.
//
// (Presumably TSan implements its own `pthread` interface,
// which is why it isn't required.)
//
// See: https://reviews.llvm.org/D39254
platform_lib_str = gb_string_appendc(platform_lib_str, "-lpthread ");
}
// FreeBSD pkg installs third-party shared libraries in /usr/local/lib.
platform_lib_str = gb_string_appendc(platform_lib_str, "-Wl,-L/usr/local/lib ");
} else if (build_context.metrics.os == TargetOs_openbsd) {
+56 -66
View File
@@ -2504,7 +2504,6 @@ gb_internal String lb_filepath_obj_for_module(lbModule *m) {
gbString path = gb_string_make_length(heap_allocator(), basename.text, basename.len);
path = gb_string_appendc(path, "/");
path = gb_string_append_length(path, name.text, name.len);
if (USE_SEPARATE_MODULES) {
GB_ASSERT(m->module_name != nullptr);
@@ -2516,6 +2515,8 @@ gb_internal String lb_filepath_obj_for_module(lbModule *m) {
}
path = gb_string_append_length(path, s.text, s.len);
} else {
path = gb_string_append_length(path, name.text, name.len);
}
if (use_temporary_directory) {
@@ -2526,38 +2527,15 @@ gb_internal String lb_filepath_obj_for_module(lbModule *m) {
String ext = {};
if (build_context.build_mode == BuildMode_Assembly) {
ext = STR_LIT(".S");
ext = STR_LIT("S");
} else if (build_context.build_mode == BuildMode_Object) {
// Allow a user override for the object extension.
ext = build_context.build_paths[BuildPath_Output].ext;
} else {
if (is_arch_wasm()) {
ext = STR_LIT(".wasm.o");
} else {
switch (build_context.metrics.os) {
case TargetOs_windows:
ext = STR_LIT(".obj");
break;
default:
case TargetOs_darwin:
case TargetOs_linux:
case TargetOs_essence:
ext = STR_LIT(".o");
break;
case TargetOs_freestanding:
switch (build_context.metrics.abi) {
default:
case TargetABI_Default:
case TargetABI_SysV:
ext = STR_LIT(".o");
break;
case TargetABI_Win64:
ext = STR_LIT(".obj");
break;
}
break;
}
}
ext = infer_object_extension_from_build_context();
}
path = gb_string_append_length(path, ".", 1);
path = gb_string_append_length(path, ext.text, ext.len);
return make_string(cast(u8 *)path, gb_string_length(path));
@@ -3376,40 +3354,40 @@ gb_internal bool lb_generate_code(lbGenerator *gen) {
lb_add_raddbg_string(m, "type_view: {type: \"string\", expr: \"array(data, len)\"}");
// column major matrices
lb_add_raddbg_string(m, "type_view: {type: \"matrix[1, ?]?\", expr: \"table($.data, $[0])\"}");
lb_add_raddbg_string(m, "type_view: {type: \"matrix[2, ?]?\", expr: \"table($.data, $[0], $[1])\"}");
lb_add_raddbg_string(m, "type_view: {type: \"matrix[3, ?]?\", expr: \"table($.data, $[0], $[1], $[2])\"}");
lb_add_raddbg_string(m, "type_view: {type: \"matrix[4, ?]?\", expr: \"table($.data, $[0], $[1], $[2], $[3])\"}");
lb_add_raddbg_string(m, "type_view: {type: \"matrix[5, ?]?\", expr: \"table($.data, $[0], $[1], $[2], $[3], $[4])\"}");
lb_add_raddbg_string(m, "type_view: {type: \"matrix[6, ?]?\", expr: \"table($.data, $[0], $[1], $[2], $[3], $[4], $[5])\"}");
lb_add_raddbg_string(m, "type_view: {type: \"matrix[7, ?]?\", expr: \"table($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6])\"}");
lb_add_raddbg_string(m, "type_view: {type: \"matrix[8, ?]?\", expr: \"table($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7])\"}");
lb_add_raddbg_string(m, "type_view: {type: \"matrix[9, ?]?\", expr: \"table($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8])\"}");
lb_add_raddbg_string(m, "type_view: {type: \"matrix[10, ?]?\", expr: \"table($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9])\"}");
lb_add_raddbg_string(m, "type_view: {type: \"matrix[11, ?]?\", expr: \"table($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9], $[10])\"}");
lb_add_raddbg_string(m, "type_view: {type: \"matrix[12, ?]?\", expr: \"table($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9], $[10], $[11])\"}");
lb_add_raddbg_string(m, "type_view: {type: \"matrix[13, ?]?\", expr: \"table($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9], $[10], $[11], $[12])\"}");
lb_add_raddbg_string(m, "type_view: {type: \"matrix[14, ?]?\", expr: \"table($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9], $[10], $[11], $[12], $[13])\"}");
lb_add_raddbg_string(m, "type_view: {type: \"matrix[15, ?]?\", expr: \"table($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9], $[10], $[11], $[12], $[13], $[14])\"}");
lb_add_raddbg_string(m, "type_view: {type: \"matrix[16, ?]?\", expr: \"table($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9], $[10], $[11], $[12], $[13], $[14], $[15])\"}");
lb_add_raddbg_string(m, "type_view: {type: \"matrix[1, ?]?\", expr: \"columns($.data, $[0])\"}");
lb_add_raddbg_string(m, "type_view: {type: \"matrix[2, ?]?\", expr: \"columns($.data, $[0], $[1])\"}");
lb_add_raddbg_string(m, "type_view: {type: \"matrix[3, ?]?\", expr: \"columns($.data, $[0], $[1], $[2])\"}");
lb_add_raddbg_string(m, "type_view: {type: \"matrix[4, ?]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3])\"}");
lb_add_raddbg_string(m, "type_view: {type: \"matrix[5, ?]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4])\"}");
lb_add_raddbg_string(m, "type_view: {type: \"matrix[6, ?]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4], $[5])\"}");
lb_add_raddbg_string(m, "type_view: {type: \"matrix[7, ?]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6])\"}");
lb_add_raddbg_string(m, "type_view: {type: \"matrix[8, ?]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7])\"}");
lb_add_raddbg_string(m, "type_view: {type: \"matrix[9, ?]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8])\"}");
lb_add_raddbg_string(m, "type_view: {type: \"matrix[10, ?]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9])\"}");
lb_add_raddbg_string(m, "type_view: {type: \"matrix[11, ?]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9], $[10])\"}");
lb_add_raddbg_string(m, "type_view: {type: \"matrix[12, ?]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9], $[10], $[11])\"}");
lb_add_raddbg_string(m, "type_view: {type: \"matrix[13, ?]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9], $[10], $[11], $[12])\"}");
lb_add_raddbg_string(m, "type_view: {type: \"matrix[14, ?]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9], $[10], $[11], $[12], $[13])\"}");
lb_add_raddbg_string(m, "type_view: {type: \"matrix[15, ?]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9], $[10], $[11], $[12], $[13], $[14])\"}");
lb_add_raddbg_string(m, "type_view: {type: \"matrix[16, ?]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9], $[10], $[11], $[12], $[13], $[14], $[15])\"}");
// row major matrices
lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 1]?\", expr: \"table($.data, $[0])\"}");
lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 2]?\", expr: \"table($.data, $[0], $[1])\"}");
lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 3]?\", expr: \"table($.data, $[0], $[1], $[2])\"}");
lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 4]?\", expr: \"table($.data, $[0], $[1], $[2], $[3])\"}");
lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 5]?\", expr: \"table($.data, $[0], $[1], $[2], $[3], $[4])\"}");
lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 6]?\", expr: \"table($.data, $[0], $[1], $[2], $[3], $[4], $[5])\"}");
lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 7]?\", expr: \"table($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6])\"}");
lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 8]?\", expr: \"table($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7])\"}");
lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 9]?\", expr: \"table($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8])\"}");
lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 10]?\", expr: \"table($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9])\"}");
lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 11]?\", expr: \"table($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9], $[10])\"}");
lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 12]?\", expr: \"table($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9], $[10], $[11])\"}");
lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 13]?\", expr: \"table($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9], $[10], $[11], $[12])\"}");
lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 14]?\", expr: \"table($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9], $[10], $[11], $[12], $[13])\"}");
lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 15]?\", expr: \"table($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9], $[10], $[11], $[12], $[13], $[14])\"}");
lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 16]?\", expr: \"table($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9], $[10], $[11], $[12], $[13], $[14], $[15])\"}");
lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 1]?\", expr: \"columns($.data, $[0])\"}");
lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 2]?\", expr: \"columns($.data, $[0], $[1])\"}");
lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 3]?\", expr: \"columns($.data, $[0], $[1], $[2])\"}");
lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 4]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3])\"}");
lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 5]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4])\"}");
lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 6]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4], $[5])\"}");
lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 7]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6])\"}");
lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 8]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7])\"}");
lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 9]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8])\"}");
lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 10]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9])\"}");
lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 11]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9], $[10])\"}");
lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 12]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9], $[10], $[11])\"}");
lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 13]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9], $[10], $[11], $[12])\"}");
lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 14]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9], $[10], $[11], $[12], $[13])\"}");
lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 15]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9], $[10], $[11], $[12], $[13], $[14])\"}");
lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 16]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9], $[10], $[11], $[12], $[13], $[14], $[15])\"}");
TEMPORARY_ALLOCATOR_GUARD();
@@ -3513,36 +3491,48 @@ gb_internal bool lb_generate_code(lbGenerator *gen) {
if (build_context.sanitizer_flags & SanitizerFlag_Address) {
if (build_context.metrics.os == TargetOs_windows) {
switch (build_context.metrics.os) {
case TargetOs_windows: {
auto paths = array_make<String>(heap_allocator(), 0, 1);
String path = concatenate_strings(permanent_allocator(), build_context.ODIN_ROOT, str_lit("\\bin\\llvm\\windows\\clang_rt.asan-x86_64.lib"));
array_add(&paths, path);
Entity *lib = alloc_entity_library_name(nullptr, make_token_ident("asan_lib"), nullptr, slice_from_array(paths), str_lit("asan_lib"));
array_add(&gen->foreign_libraries, lib);
} else if (build_context.metrics.os == TargetOs_darwin || build_context.metrics.os == TargetOs_linux) {
} break;
case TargetOs_darwin:
case TargetOs_linux:
case TargetOs_freebsd:
if (!build_context.extra_linker_flags.text) {
build_context.extra_linker_flags = str_lit("-fsanitize=address");
} else {
build_context.extra_linker_flags = concatenate_strings(permanent_allocator(), build_context.extra_linker_flags, str_lit(" -fsanitize=address"));
}
break;
}
}
if (build_context.sanitizer_flags & SanitizerFlag_Memory) {
if (build_context.metrics.os == TargetOs_darwin || build_context.metrics.os == TargetOs_linux) {
switch (build_context.metrics.os) {
case TargetOs_linux:
case TargetOs_freebsd:
if (!build_context.extra_linker_flags.text) {
build_context.extra_linker_flags = str_lit("-fsanitize=memory");
} else {
build_context.extra_linker_flags = concatenate_strings(permanent_allocator(), build_context.extra_linker_flags, str_lit(" -fsanitize=memory"));
}
break;
}
}
if (build_context.sanitizer_flags & SanitizerFlag_Thread) {
if (build_context.metrics.os == TargetOs_darwin || build_context.metrics.os == TargetOs_linux) {
switch (build_context.metrics.os) {
case TargetOs_darwin:
case TargetOs_linux:
case TargetOs_freebsd:
if (!build_context.extra_linker_flags.text) {
build_context.extra_linker_flags = str_lit("-fsanitize=thread");
} else {
build_context.extra_linker_flags = concatenate_strings(permanent_allocator(), build_context.extra_linker_flags, str_lit(" -fsanitize=thread"));
}
break;
}
}
+39 -5
View File
@@ -312,6 +312,7 @@ enum BuildFlagKind {
BuildFlag_Collection,
BuildFlag_Define,
BuildFlag_BuildMode,
BuildFlag_KeepExecutable,
BuildFlag_Target,
BuildFlag_Subtarget,
BuildFlag_Debug,
@@ -531,6 +532,7 @@ gb_internal bool parse_build_flags(Array<String> args) {
add_flag(&build_flags, BuildFlag_Collection, str_lit("collection"), BuildFlagParam_String, Command__does_check);
add_flag(&build_flags, BuildFlag_Define, str_lit("define"), BuildFlagParam_String, Command__does_check, true);
add_flag(&build_flags, BuildFlag_BuildMode, str_lit("build-mode"), BuildFlagParam_String, Command__does_build); // Commands_build is not used to allow for a better error message
add_flag(&build_flags, BuildFlag_KeepExecutable, str_lit("keep-executable"), BuildFlagParam_None, Command__does_build | Command_test);
add_flag(&build_flags, BuildFlag_Target, str_lit("target"), BuildFlagParam_String, Command__does_check);
add_flag(&build_flags, BuildFlag_Subtarget, str_lit("subtarget"), BuildFlagParam_String, Command__does_check);
add_flag(&build_flags, BuildFlag_Debug, str_lit("debug"), BuildFlagParam_None, Command__does_check);
@@ -1193,6 +1195,9 @@ gb_internal bool parse_build_flags(Array<String> args) {
break;
}
case BuildFlag_KeepExecutable:
build_context.keep_executable = true;
break;
case BuildFlag_Debug:
build_context.ODIN_DEBUG = true;
@@ -1622,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;
}
@@ -1633,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;
}
@@ -1641,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]));
@@ -2381,6 +2386,12 @@ gb_internal int print_show_help(String const arg0, String command, String option
}
}
if (test_only) {
if (print_flag("-build-only")) {
print_usage_line(2, "Only builds the test executable; does not automatically run it afterwards.");
}
}
if (check) {
if (print_flag("-collection:<name>=<filepath>")) {
print_usage_line(2, "Defines a library collection used for imports.");
@@ -2543,6 +2554,14 @@ gb_internal int print_show_help(String const arg0, String command, String option
}
}
if (test_only || run_or_build) {
if (print_flag("-keep-executable")) {
print_usage_line(2, "Keep the executable generated by `odin test` or `odin run` after running it. We clean it up by default.");
print_usage_line(2, "If you build your program or test using `odin build`, the compiler does not automatically execute");
print_usage_line(2, "the resulting program, and this option is not applicable.");
}
}
if (run_or_build) {
if (print_flag("-linker:<string>")) {
print_usage_line(2, "Specify the linker to use.");
@@ -3866,6 +3885,21 @@ end_of_code_gen:;
defer (gb_free(heap_allocator(), exe_name.text));
system_must_exec_command_line_app("odin run", "\"%.*s\" %.*s", LIT(exe_name), LIT(run_args_string));
if (!build_context.keep_executable) {
char const *filename = cast(char const *)exe_name.text;
gb_file_remove(filename);
if (build_context.ODIN_DEBUG) {
if (build_context.metrics.os == TargetOs_windows || build_context.metrics.os == TargetOs_darwin) {
String symbol_path = path_to_string(heap_allocator(), build_context.build_paths[BuildPath_Symbols]);
defer (gb_free(heap_allocator(), symbol_path.text));
filename = cast(char const *)symbol_path.text;
gb_file_remove(filename);
}
}
}
}
return 0;
}
+9 -1
View File
@@ -3274,6 +3274,8 @@ gb_internal Ast *parse_atom_expr(AstFile *f, Ast *operand, bool lhs) {
case Token_OpenBracket: {
bool prev_allow_range = f->allow_range;
f->allow_range = false;
defer (f->allow_range = prev_allow_range);
Token open = {}, close = {}, interval = {};
Ast *indices[2] = {};
@@ -3282,6 +3284,13 @@ gb_internal Ast *parse_atom_expr(AstFile *f, Ast *operand, bool lhs) {
f->expr_level++;
open = expect_token(f, Token_OpenBracket);
if (f->curr_token.kind == Token_CloseBracket) {
error(f->curr_token, "Expected an operand, got ]");
close = expect_token(f, Token_CloseBracket);
operand = ast_index_expr(f, operand, nullptr, open, close);
break;
}
switch (f->curr_token.kind) {
case Token_Ellipsis:
case Token_RangeFull:
@@ -3331,7 +3340,6 @@ gb_internal Ast *parse_atom_expr(AstFile *f, Ast *operand, bool lhs) {
operand = ast_index_expr(f, operand, indices[0], open, close);
}
f->allow_range = prev_allow_range;
} break;
case Token_Pointer: // Deference
+1
View File
@@ -968,6 +968,7 @@ gb_internal void tokenizer_get_token(Tokenizer *t, Token *token, int repeat=0) {
advance_to_next_rune(t);
for (isize comment_scope = 1; comment_scope > 0; /**/) {
if (t->curr_rune == GB_RUNE_EOF) {
tokenizer_err(t, "Multi-line comment not terminated");
break;
} else if (t->curr_rune == '/') {
advance_to_next_rune(t);