Merge remote-tracking branch 'offical/master'

# Conflicts:
#	vendor/raylib/raygui.odin
#	vendor/raylib/raylib.odin
This commit is contained in:
ed
2025-01-06 10:51:25 -05:00
105 changed files with 7185 additions and 3321 deletions
+13 -7
View File
@@ -324,6 +324,18 @@ u64 get_vet_flag_from_name(String const &name) {
return VetFlag_NONE;
}
enum OptInFeatureFlags : u64 {
OptInFeatureFlag_NONE = 0,
OptInFeatureFlag_DynamicLiterals = 1u<<0,
};
u64 get_feature_flag_from_name(String const &name) {
if (name == "dynamic-literals") {
return OptInFeatureFlag_DynamicLiterals;
}
return OptInFeatureFlag_NONE;
}
enum SanitizerFlags : u32 {
SanitizerFlag_NONE = 0,
@@ -429,7 +441,6 @@ struct BuildContext {
bool ignore_unknown_attributes;
bool no_bounds_check;
bool no_type_assert;
bool no_dynamic_literals;
bool no_output_files;
bool no_crt;
bool no_rpath;
@@ -1855,11 +1866,6 @@ gb_internal bool init_build_paths(String init_filename) {
produces_output_file = true;
}
if (build_context.ODIN_DEFAULT_TO_NIL_ALLOCATOR ||
build_context.ODIN_DEFAULT_TO_PANIC_ALLOCATOR) {
bc->no_dynamic_literals = true;
}
if (!produces_output_file) {
// Command doesn't produce output files. We're done.
return true;
@@ -2054,7 +2060,7 @@ gb_internal bool init_build_paths(String init_filename) {
// 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 || build_context.build_mode != BuildMode_Executable) {
if (build_context.metrics.os == TargetOs_windows || is_arch_wasm() || build_context.build_mode != BuildMode_Executable) {
bc->build_paths[BuildPath_Output].ext = copy_string(ha, output_extension);
}
}
+48 -50
View File
@@ -94,12 +94,14 @@ gb_internal Type *check_init_variable(CheckerContext *ctx, Entity *e, Operand *o
return nullptr;
}
if (e2->state.load() != EntityState_Resolved) {
gbString str = type_to_string(t);
defer (gb_string_free(str));
error(e->token, "Invalid use of a polymorphic type '%s' in %.*s", str, LIT(context_name));
e->type = t_invalid;
e->type = t;
return nullptr;
}
gbString str = type_to_string(t);
defer (gb_string_free(str));
error(operand->expr, "Invalid use of a non-specialized polymorphic type '%s' in %.*s", str, LIT(context_name));
e->type = t_invalid;
return nullptr;
} else if (is_type_empty_union(t)) {
gbString str = type_to_string(t);
defer (gb_string_free(str));
@@ -971,6 +973,43 @@ gb_internal void check_objc_methods(CheckerContext *ctx, Entity *e, AttributeCon
}
}
gb_internal void check_foreign_procedure(CheckerContext *ctx, Entity *e, DeclInfo *d) {
GB_ASSERT(e != nullptr);
GB_ASSERT(e->kind == Entity_Procedure);
String name = e->Procedure.link_name;
mutex_lock(&ctx->info->foreign_mutex);
auto *fp = &ctx->info->foreigns;
StringHashKey key = string_hash_string(name);
Entity **found = string_map_get(fp, key);
if (found && e != *found) {
Entity *f = *found;
TokenPos pos = f->token.pos;
Type *this_type = base_type(e->type);
Type *other_type = base_type(f->type);
if (is_type_proc(this_type) && is_type_proc(other_type)) {
if (!are_signatures_similar_enough(this_type, other_type)) {
error(d->proc_lit,
"Redeclaration of foreign procedure '%.*s' with different type signatures\n"
"\tat %s",
LIT(name), token_pos_to_string(pos));
}
} else if (!signature_parameter_similar_enough(this_type, other_type)) {
error(d->proc_lit,
"Foreign entity '%.*s' previously declared elsewhere with a different type\n"
"\tat %s",
LIT(name), token_pos_to_string(pos));
}
} else if (name == "main") {
error(d->proc_lit, "The link name 'main' is reserved for internal use");
} else {
string_map_set(fp, key, e);
}
mutex_unlock(&ctx->info->foreign_mutex);
}
gb_internal void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) {
GB_ASSERT(e->type == nullptr);
if (d->proc_lit->kind != Ast_ProcLit) {
@@ -1307,57 +1346,16 @@ gb_internal void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) {
name = e->Procedure.link_name;
}
Entity *foreign_library = init_entity_foreign_library(ctx, e);
if (is_arch_wasm() && foreign_library != nullptr) {
String module_name = str_lit("env");
GB_ASSERT (foreign_library->kind == Entity_LibraryName);
if (foreign_library->LibraryName.paths.count != 1) {
error(foreign_library->token, "'foreign import' for '%.*s' architecture may only have one path, got %td",
LIT(target_arch_names[build_context.metrics.arch]), foreign_library->LibraryName.paths.count);
}
if (foreign_library->LibraryName.paths.count >= 1) {
module_name = foreign_library->LibraryName.paths[0];
}
if (!string_ends_with(module_name, str_lit(".o"))) {
name = concatenate3_strings(permanent_allocator(), module_name, WASM_MODULE_NAME_SEPARATOR, name);
}
}
e->Procedure.is_foreign = true;
e->Procedure.link_name = name;
e->Procedure.foreign_library = foreign_library;
mutex_lock(&ctx->info->foreign_mutex);
auto *fp = &ctx->info->foreigns;
StringHashKey key = string_hash_string(name);
Entity **found = string_map_get(fp, key);
if (found && e != *found) {
Entity *f = *found;
TokenPos pos = f->token.pos;
Type *this_type = base_type(e->type);
Type *other_type = base_type(f->type);
if (is_type_proc(this_type) && is_type_proc(other_type)) {
if (!are_signatures_similar_enough(this_type, other_type)) {
error(d->proc_lit,
"Redeclaration of foreign procedure '%.*s' with different type signatures\n"
"\tat %s",
LIT(name), token_pos_to_string(pos));
}
} else if (!signature_parameter_similar_enough(this_type, other_type)) {
error(d->proc_lit,
"Foreign entity '%.*s' previously declared elsewhere with a different type\n"
"\tat %s",
LIT(name), token_pos_to_string(pos));
}
} else if (name == "main") {
error(d->proc_lit, "The link name 'main' is reserved for internal use");
if (is_arch_wasm() && foreign_library != nullptr) {
// NOTE(bill): this must be delayed because the foreign import paths might not be evaluated yet until much later
mpsc_enqueue(&ctx->info->foreign_decls_to_check, e);
} else {
string_map_set(fp, key, e);
check_foreign_procedure(ctx, e, d);
}
mutex_unlock(&ctx->info->foreign_mutex);
} else {
String name = e->token.string;
if (e->Procedure.link_name.len > 0) {
+53 -10
View File
@@ -3672,6 +3672,13 @@ gb_internal bool check_binary_array_expr(CheckerContext *c, Token op, Operand *x
}
}
}
if (is_type_simd_vector(x->type) && !is_type_simd_vector(y->type)) {
if (check_is_assignable_to(c, y, x->type)) {
if (check_binary_op(c, x, op)) {
return true;
}
}
}
return false;
}
@@ -4556,6 +4563,19 @@ gb_internal void convert_to_typed(CheckerContext *c, Operand *operand, Type *tar
break;
}
case Type_SimdVector: {
Type *elem = base_array_type(t);
if (check_is_assignable_to(c, operand, elem)) {
operand->mode = Addressing_Value;
} else {
operand->mode = Addressing_Invalid;
convert_untyped_error(c, operand, target_type);
return;
}
break;
}
case Type_Matrix: {
Type *elem = base_array_type(t);
if (check_is_assignable_to(c, operand, elem)) {
@@ -8727,6 +8747,18 @@ gb_internal ExprKind check_basic_directive_expr(CheckerContext *c, Operand *o, A
error(node, "#caller_expression may only be used as a default argument parameter");
o->type = t_string;
o->mode = Addressing_Value;
} else if (name == "branch_location") {
if (!c->in_defer) {
error(node, "#branch_location may only be used within a 'defer' statement");
} else if (c->curr_proc_decl) {
Entity *e = c->curr_proc_decl->entity;
if (e != nullptr) {
GB_ASSERT(e->kind == Entity_Procedure);
e->Procedure.uses_branch_location = true;
}
}
o->type = t_source_code_location;
o->mode = Addressing_Value;
} else {
if (name == "location") {
init_core_source_code_location(c->checker);
@@ -9341,6 +9373,23 @@ gb_internal bool is_expr_inferred_fixed_array(Ast *type_expr) {
return false;
}
gb_internal bool check_for_dynamic_literals(CheckerContext *c, Ast *node, AstCompoundLit *cl) {
if (cl->elems.count > 0 && (check_feature_flags(c, node) & OptInFeatureFlag_DynamicLiterals) == 0) {
ERROR_BLOCK();
error(node, "Compound literals of dynamic types are disabled by default");
error_line("\tSuggestion: If you want to enable them for this specific file, add '#+feature dynamic-literals' at the top of the file\n");
error_line("\tWarning: Please understand that dynamic literals will implicitly allocate using the current 'context.allocator' in that scope\n");
if (build_context.ODIN_DEFAULT_TO_NIL_ALLOCATOR) {
error_line("\tWarning: As '-default-to-panic-allocator' has been set, the dynamic compound literal may not be initialized as expected\n");
} else if (build_context.ODIN_DEFAULT_TO_PANIC_ALLOCATOR) {
error_line("\tWarning: As '-default-to-panic-allocator' has been set, the dynamic compound literal may not be initialized as expected\n");
}
return false;
}
return cl->elems.count > 0;
}
gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast *node, Type *type_hint) {
ExprKind kind = Expr_Expr;
ast_node(cl, CompoundLit, node);
@@ -9541,11 +9590,6 @@ gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast *
elem_type = t->DynamicArray.elem;
context_name = str_lit("dynamic array literal");
is_constant = false;
if (!build_context.no_dynamic_literals) {
add_package_dependency(c, "runtime", "__dynamic_array_reserve");
add_package_dependency(c, "runtime", "__dynamic_array_append");
}
} else if (t->kind == Type_SimdVector) {
elem_type = t->SimdVector.elem;
context_name = str_lit("simd vector literal");
@@ -9720,8 +9764,9 @@ gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast *
if (t->kind == Type_DynamicArray) {
if (build_context.no_dynamic_literals && cl->elems.count) {
error(node, "Compound literals of dynamic types have been disabled");
if (check_for_dynamic_literals(c, node, cl)) {
add_package_dependency(c, "runtime", "__dynamic_array_reserve");
add_package_dependency(c, "runtime", "__dynamic_array_append");
}
}
@@ -10110,9 +10155,7 @@ gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast *
}
}
if (build_context.no_dynamic_literals && cl->elems.count) {
error(node, "Compound literals of dynamic types have been disabled");
} else {
if (check_for_dynamic_literals(c, node, cl)) {
add_map_reserve_dependencies(c);
add_map_set_dependencies(c);
}
+8 -1
View File
@@ -2440,8 +2440,12 @@ gb_internal bool check_procedure_type(CheckerContext *ctx, Type *type, Ast *proc
bool success = true;
isize specialization_count = 0;
Type *params = check_get_params(c, c->scope, pt->params, &variadic, &variadic_index, &success, &specialization_count, operands);
Type *results = check_get_results(c, c->scope, pt->results);
bool no_poly_return = c->disallow_polymorphic_return_types;
c->disallow_polymorphic_return_types = c->scope == c->polymorphic_scope;
// NOTE(zen3ger): if the parapoly scope is the current proc's scope, then the return types shall not declare new poly vars
Type *results = check_get_results(c, c->scope, pt->results);
c->disallow_polymorphic_return_types = no_poly_return;
isize param_count = 0;
isize result_count = 0;
@@ -3383,6 +3387,9 @@ gb_internal bool check_type_internal(CheckerContext *ctx, Ast *e, Type **type, T
}
Type *t = alloc_type_generic(ctx->scope, 0, token.string, specific);
if (ctx->allow_polymorphic_types) {
if (ctx->disallow_polymorphic_return_types) {
error(ident, "Undeclared polymorphic parameter '%.*s' in return type", LIT(token.string));
}
Scope *ps = ctx->polymorphic_scope;
Scope *s = ctx->scope;
Scope *entity_scope = s;
+51 -1
View File
@@ -542,6 +542,23 @@ gb_internal u64 check_vet_flags(Ast *node) {
return ast_file_vet_flags(file);
}
gb_internal u64 check_feature_flags(CheckerContext *c, Ast *node) {
AstFile *file = c->file;
if (file == nullptr &&
c->curr_proc_decl &&
c->curr_proc_decl->proc_lit) {
file = c->curr_proc_decl->proc_lit->file();
}
if (file == nullptr) {
file = node->file();
}
if (file != nullptr && file->feature_flags_set) {
return file->feature_flags;
}
return 0;
}
enum VettedEntityKind {
VettedEntity_Invalid,
@@ -1164,7 +1181,6 @@ gb_internal void init_universal(void) {
add_global_bool_constant("ODIN_NO_BOUNDS_CHECK", build_context.no_bounds_check);
add_global_bool_constant("ODIN_NO_TYPE_ASSERT", build_context.no_type_assert);
add_global_bool_constant("ODIN_DEFAULT_TO_PANIC_ALLOCATOR", bc->ODIN_DEFAULT_TO_PANIC_ALLOCATOR);
add_global_bool_constant("ODIN_NO_DYNAMIC_LITERALS", bc->no_dynamic_literals);
add_global_bool_constant("ODIN_NO_CRT", bc->no_crt);
add_global_bool_constant("ODIN_USE_SEPARATE_MODULES", bc->use_separate_modules);
add_global_bool_constant("ODIN_TEST", bc->command_kind == Command_test);
@@ -1356,6 +1372,7 @@ gb_internal void init_checker_info(CheckerInfo *i) {
mpsc_init(&i->required_global_variable_queue, a); // 1<<10);
mpsc_init(&i->required_foreign_imports_through_force_queue, a); // 1<<10);
mpsc_init(&i->foreign_imports_to_check_fullpaths, a); // 1<<10);
mpsc_init(&i->foreign_decls_to_check, a); // 1<<10);
mpsc_init(&i->intrinsics_entry_point_usage, a); // 1<<10); // just waste some memory here, even if it probably never used
string_map_init(&i->load_directory_cache);
@@ -1382,6 +1399,7 @@ gb_internal void destroy_checker_info(CheckerInfo *i) {
mpsc_destroy(&i->required_global_variable_queue);
mpsc_destroy(&i->required_foreign_imports_through_force_queue);
mpsc_destroy(&i->foreign_imports_to_check_fullpaths);
mpsc_destroy(&i->foreign_decls_to_check);
map_destroy(&i->objc_msgSend_types);
string_map_destroy(&i->load_file_cache);
@@ -5094,6 +5112,38 @@ gb_internal void check_foreign_import_fullpaths(Checker *c) {
e->LibraryName.paths = fl->fullpaths;
}
for (Entity *e = nullptr; mpsc_dequeue(&c->info.foreign_decls_to_check, &e); /**/) {
GB_ASSERT(e != nullptr);
if (e->kind != Entity_Procedure) {
continue;
}
if (!is_arch_wasm()) {
continue;
}
Entity *foreign_library = e->Procedure.foreign_library;
GB_ASSERT(foreign_library != nullptr);
String name = e->Procedure.link_name;
String module_name = str_lit("env");
GB_ASSERT (foreign_library->kind == Entity_LibraryName);
if (foreign_library->LibraryName.paths.count != 1) {
error(foreign_library->token, "'foreign import' for '%.*s' architecture may only have one path, got %td",
LIT(target_arch_names[build_context.metrics.arch]), foreign_library->LibraryName.paths.count);
}
if (foreign_library->LibraryName.paths.count >= 1) {
module_name = foreign_library->LibraryName.paths[0];
}
if (!string_ends_with(module_name, str_lit(".o"))) {
name = concatenate3_strings(permanent_allocator(), module_name, WASM_MODULE_NAME_SEPARATOR, name);
}
e->Procedure.link_name = name;
check_foreign_procedure(&ctx, e, e->decl_info);
}
}
gb_internal void check_add_foreign_import_decl(CheckerContext *ctx, Ast *decl) {
+2
View File
@@ -461,6 +461,7 @@ struct CheckerInfo {
MPSCQueue<Entity *> required_global_variable_queue;
MPSCQueue<Entity *> required_foreign_imports_through_force_queue;
MPSCQueue<Entity *> foreign_imports_to_check_fullpaths;
MPSCQueue<Entity *> foreign_decls_to_check;
MPSCQueue<Ast *> intrinsics_entry_point_usage;
@@ -521,6 +522,7 @@ struct CheckerContext {
bool in_enum_type;
bool collect_delayed_decls;
bool allow_polymorphic_types;
bool disallow_polymorphic_return_types; // NOTE(zen3ger): no poly type decl in return types
bool no_polymorphic_errors;
bool hide_polymorphic_errors;
bool in_polymorphic_specialization;
+1
View File
@@ -256,6 +256,7 @@ struct Entity {
bool entry_point_only : 1;
bool has_instrumentation : 1;
bool is_memcpy_like : 1;
bool uses_branch_location : 1;
} Procedure;
struct {
Array<Entity *> entities;
-2
View File
@@ -1096,8 +1096,6 @@ gb_internal void lb_internal_dynamic_map_set(lbProcedure *p, lbValue const &map_
}
gb_internal lbValue lb_dynamic_map_reserve(lbProcedure *p, lbValue const &map_ptr, isize const capacity, TokenPos const &pos) {
GB_ASSERT(!build_context.no_dynamic_literals);
TEMPORARY_ALLOCATOR_GUARD();
String proc_name = {};
+8 -1
View File
@@ -359,6 +359,10 @@ struct lbProcedure {
bool in_multi_assignment;
Array<LLVMValueRef> raw_input_parameters;
bool uses_branch_location;
TokenPos branch_location_pos;
TokenPos curr_token_pos;
Array<lbVariadicReuseSlices> variadic_reuses;
lbAddr variadic_reuse_base_array_ptr;
@@ -444,7 +448,8 @@ gb_internal lbValue lb_emit_matrix_ev(lbProcedure *p, lbValue s, isize row, isiz
gb_internal lbValue lb_emit_arith(lbProcedure *p, TokenKind op, lbValue lhs, lbValue rhs, Type *type);
gb_internal lbValue lb_emit_byte_swap(lbProcedure *p, lbValue value, Type *end_type);
gb_internal void lb_emit_defer_stmts(lbProcedure *p, lbDeferExitKind kind, lbBlock *block);
gb_internal void lb_emit_defer_stmts(lbProcedure *p, lbDeferExitKind kind, lbBlock *block, TokenPos pos);
gb_internal void lb_emit_defer_stmts(lbProcedure *p, lbDeferExitKind kind, lbBlock *block, Ast *node);
gb_internal lbValue lb_emit_transmute(lbProcedure *p, lbValue value, Type *t);
gb_internal lbValue lb_emit_comp(lbProcedure *p, TokenKind op_kind, lbValue left, lbValue right);
gb_internal lbValue lb_emit_call(lbProcedure *p, lbValue value, Array<lbValue> const &args, ProcInlining inlining = ProcInlining_none);
@@ -742,3 +747,5 @@ gb_global char const *llvm_linkage_strings[] = {
};
#define ODIN_METADATA_IS_PACKED str_lit("odin-is-packed")
#define ODIN_METADATA_MIN_ALIGN str_lit("odin-min-align")
#define ODIN_METADATA_MAX_ALIGN str_lit("odin-max-align")
+30 -5
View File
@@ -2817,6 +2817,12 @@ gb_internal lbValue lb_emit_comp(lbProcedure *p, TokenKind op_kind, lbValue left
Type *it = bit_set_to_int(a);
lbValue lhs = lb_emit_transmute(p, left, it);
lbValue rhs = lb_emit_transmute(p, right, it);
if (is_type_different_to_arch_endianness(it)) {
it = integer_endian_type_to_platform_type(it);
lhs = lb_emit_byte_swap(p, lhs, it);
rhs = lb_emit_byte_swap(p, rhs, it);
}
lbValue res = lb_emit_arith(p, Token_And, lhs, rhs, it);
if (op_kind == Token_Lt || op_kind == Token_LtEq) {
@@ -2914,6 +2920,12 @@ gb_internal lbValue lb_emit_comp(lbProcedure *p, TokenKind op_kind, lbValue left
}
}
if (is_type_different_to_arch_endianness(left.type)) {
Type *pt = integer_endian_type_to_platform_type(left.type);
lhs = lb_emit_byte_swap(p, {lhs, pt}, pt).value;
rhs = lb_emit_byte_swap(p, {rhs, pt}, pt).value;
}
res.value = LLVMBuildICmp(p->builder, pred, lhs, rhs, "");
} else if (is_type_float(a)) {
LLVMRealPredicate pred = {};
@@ -2925,6 +2937,13 @@ gb_internal lbValue lb_emit_comp(lbProcedure *p, TokenKind op_kind, lbValue left
case Token_LtEq: pred = LLVMRealOLE; break;
case Token_NotEq: pred = LLVMRealONE; break;
}
if (is_type_different_to_arch_endianness(left.type)) {
Type *pt = integer_endian_type_to_platform_type(left.type);
left = lb_emit_byte_swap(p, left, pt);
right = lb_emit_byte_swap(p, right, pt);
}
res.value = LLVMBuildFCmp(p->builder, pred, left.value, right.value, "");
} else if (is_type_typeid(a)) {
LLVMIntPredicate pred = {};
@@ -3483,7 +3502,13 @@ gb_internal lbValue lb_build_expr_internal(lbProcedure *p, Ast *expr) {
case_ast_node(bd, BasicDirective, expr);
TokenPos pos = bd->token.pos;
GB_PANIC("Non-constant basic literal %s - %.*s", token_pos_to_string(pos), LIT(bd->name.string));
String name = bd->name.string;
if (name == "branch_location") {
GB_ASSERT(p->uses_branch_location);
String proc_name = p->entity->token.string;
return lb_emit_source_code_location_as_global(p, proc_name, p->branch_location_pos);
}
GB_PANIC("Non-constant basic literal %s - %.*s", token_pos_to_string(pos), LIT(name));
case_end;
case_ast_node(i, Implicit, expr);
@@ -3649,7 +3674,7 @@ gb_internal lbValue lb_build_expr_internal(lbProcedure *p, Ast *expr) {
lb_emit_if(p, lb_emit_try_has_value(p, rhs), then, else_);
lb_start_block(p, else_);
lb_emit_defer_stmts(p, lbDeferExit_Branch, block);
lb_emit_defer_stmts(p, lbDeferExit_Branch, block, expr);
lb_emit_jump(p, block);
lb_start_block(p, then);
@@ -4788,7 +4813,7 @@ gb_internal lbAddr lb_build_addr_compound_lit(lbProcedure *p, Ast *expr) {
if (cl->elems.count == 0) {
break;
}
GB_ASSERT(!build_context.no_dynamic_literals);
GB_ASSERT(expr->file()->feature_flags & OptInFeatureFlag_DynamicLiterals);
lbValue err = lb_dynamic_map_reserve(p, v.addr, 2*cl->elems.count, pos);
gb_unused(err);
@@ -4877,7 +4902,7 @@ gb_internal lbAddr lb_build_addr_compound_lit(lbProcedure *p, Ast *expr) {
if (cl->elems.count == 0) {
break;
}
GB_ASSERT(!build_context.no_dynamic_literals);
GB_ASSERT(expr->file()->feature_flags & OptInFeatureFlag_DynamicLiterals);
Type *et = bt->DynamicArray.elem;
lbValue size = lb_const_int(p->module, t_int, type_size_of(et));
@@ -5474,7 +5499,7 @@ gb_internal lbAddr lb_build_addr_internal(lbProcedure *p, Ast *expr) {
lb_emit_if(p, lb_emit_try_has_value(p, rhs), then, else_);
lb_start_block(p, else_);
lb_emit_defer_stmts(p, lbDeferExit_Branch, block);
lb_emit_defer_stmts(p, lbDeferExit_Branch, block, expr);
lb_emit_jump(p, block);
lb_start_block(p, then);
+17 -1
View File
@@ -734,6 +734,17 @@ gb_internal LLVMValueRef OdinLLVMBuildLoad(lbProcedure *p, LLVMTypeRef type, LLV
if (is_packed != 0) {
LLVMSetAlignment(result, 1);
}
u64 align = LLVMGetAlignment(result);
u64 align_min = lb_get_metadata_custom_u64(p->module, value, ODIN_METADATA_MIN_ALIGN);
u64 align_max = lb_get_metadata_custom_u64(p->module, value, ODIN_METADATA_MAX_ALIGN);
if (align_min != 0 && align < align_min) {
align = align_min;
}
if (align_max != 0 && align > align_max) {
align = align_max;
}
GB_ASSERT(align <= UINT_MAX);
LLVMSetAlignment(result, (unsigned int)align);
}
return result;
@@ -2121,6 +2132,7 @@ gb_internal LLVMTypeRef lb_type_internal(lbModule *m, Type *type) {
}
i64 prev_offset = 0;
bool requires_packing = type->Struct.is_packed;
for (i32 field_index : struct_fields_index_by_increasing_offset(temporary_allocator(), type)) {
Entity *field = type->Struct.fields[field_index];
i64 offset = type->Struct.offsets[field_index];
@@ -2141,6 +2153,10 @@ gb_internal LLVMTypeRef lb_type_internal(lbModule *m, Type *type) {
field_type = t_rawptr;
}
// max_field_align might misalign items in a way that requires packing
// so check the alignment of all fields to see if packing is required.
requires_packing = requires_packing || ((offset % type_align_of(field_type)) != 0);
array_add(&fields, lb_type(m, field_type));
prev_offset = offset + type_size_of(field->type);
@@ -2155,7 +2171,7 @@ gb_internal LLVMTypeRef lb_type_internal(lbModule *m, Type *type) {
GB_ASSERT(fields[i] != nullptr);
}
LLVMTypeRef struct_type = LLVMStructTypeInContext(ctx, fields.data, cast(unsigned)fields.count, type->Struct.is_packed);
LLVMTypeRef struct_type = LLVMStructTypeInContext(ctx, fields.data, cast(unsigned)fields.count, requires_packing);
map_set(&m->struct_field_remapping, cast(void *)struct_type, field_remapping);
map_set(&m->struct_field_remapping, cast(void *)type, field_remapping);
#if 0
+5 -5
View File
@@ -125,6 +125,10 @@ gb_internal lbProcedure *lb_create_procedure(lbModule *m, Entity *entity, bool i
// map_init(&p->selector_addr, 0);
// map_init(&p->tuple_fix_map, 0);
if (p->entity != nullptr && p->entity->Procedure.uses_branch_location) {
p->uses_branch_location = true;
}
if (p->is_foreign) {
lb_add_foreign_library_path(p->module, entity->Procedure.foreign_library);
}
@@ -757,7 +761,7 @@ gb_internal void lb_end_procedure_body(lbProcedure *p) {
if (p->type->Proc.result_count == 0) {
instr = LLVMGetLastInstruction(p->curr_block->block);
if (!lb_is_instr_terminating(instr)) {
lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr);
lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr, p->body);
lb_set_debug_position_to_procedure_end(p);
LLVMBuildRetVoid(p->builder);
}
@@ -1136,10 +1140,6 @@ gb_internal lbValue lb_emit_call(lbProcedure *p, lbValue value, Array<lbValue> c
}
}
if (inlining == ProcInlining_none) {
inlining = p->inlining;
}
Type *rt = reduce_tuple_to_single_type(results);
Type *original_rt = rt;
if (split_returns) {
+52 -29
View File
@@ -208,8 +208,8 @@ gb_internal void lb_open_scope(lbProcedure *p, Scope *s) {
}
gb_internal void lb_close_scope(lbProcedure *p, lbDeferExitKind kind, lbBlock *block, bool pop_stack=true) {
lb_emit_defer_stmts(p, kind, block);
gb_internal void lb_close_scope(lbProcedure *p, lbDeferExitKind kind, lbBlock *block, Ast *node, bool pop_stack=true) {
lb_emit_defer_stmts(p, kind, block, node);
GB_ASSERT(p->scope_index > 0);
// NOTE(bill): Remove `context`s made in that scope
@@ -721,7 +721,7 @@ gb_internal void lb_build_range_interval(lbProcedure *p, AstBinaryExpr *node,
lb_build_stmt(p, rs->body);
lb_close_scope(p, lbDeferExit_Default, nullptr);
lb_close_scope(p, lbDeferExit_Default, nullptr, node->left);
lb_pop_target_list(p);
if (check != nullptr) {
@@ -854,7 +854,7 @@ gb_internal void lb_build_range_tuple(lbProcedure *p, AstRangeStmt *rs, Scope *s
lb_build_stmt(p, rs->body);
lb_close_scope(p, lbDeferExit_Default, nullptr);
lb_close_scope(p, lbDeferExit_Default, nullptr, rs->body);
lb_pop_target_list(p);
lb_emit_jump(p, loop);
lb_start_block(p, done);
@@ -976,7 +976,7 @@ gb_internal void lb_build_range_stmt_struct_soa(lbProcedure *p, AstRangeStmt *rs
lb_build_stmt(p, rs->body);
lb_close_scope(p, lbDeferExit_Default, nullptr);
lb_close_scope(p, lbDeferExit_Default, nullptr, rs->body);
lb_pop_target_list(p);
lb_emit_jump(p, loop);
lb_start_block(p, done);
@@ -1192,7 +1192,7 @@ gb_internal void lb_build_range_stmt(lbProcedure *p, AstRangeStmt *rs, Scope *sc
lb_build_stmt(p, rs->body);
lb_close_scope(p, lbDeferExit_Default, nullptr);
lb_close_scope(p, lbDeferExit_Default, nullptr, rs->body);
lb_pop_target_list(p);
lb_emit_jump(p, loop);
lb_start_block(p, done);
@@ -1363,7 +1363,7 @@ gb_internal void lb_build_unroll_range_stmt(lbProcedure *p, AstUnrollRangeStmt *
}
lb_close_scope(p, lbDeferExit_Default, nullptr);
lb_close_scope(p, lbDeferExit_Default, nullptr, rs->body);
}
gb_internal bool lb_switch_stmt_can_be_trivial_jump_table(AstSwitchStmt *ss, bool *default_found_) {
@@ -1433,6 +1433,7 @@ gb_internal void lb_build_switch_stmt(lbProcedure *p, AstSwitchStmt *ss, Scope *
ast_node(body, BlockStmt, ss->body);
isize case_count = body->stmts.count;
Ast *default_clause = nullptr;
Slice<Ast *> default_stmts = {};
lbBlock *default_fall = nullptr;
lbBlock *default_block = nullptr;
@@ -1482,6 +1483,7 @@ gb_internal void lb_build_switch_stmt(lbProcedure *p, AstSwitchStmt *ss, Scope *
if (cc->list.count == 0) {
// default case
default_clause = clause;
default_stmts = cc->stmts;
default_fall = fall;
if (switch_instr == nullptr) {
@@ -1552,7 +1554,7 @@ gb_internal void lb_build_switch_stmt(lbProcedure *p, AstSwitchStmt *ss, Scope *
lb_push_target_list(p, ss->label, done, nullptr, fall);
lb_open_scope(p, body->scope);
lb_build_stmt_list(p, cc->stmts);
lb_close_scope(p, lbDeferExit_Default, body);
lb_close_scope(p, lbDeferExit_Default, body, clause);
lb_pop_target_list(p);
lb_emit_jump(p, done);
@@ -1570,13 +1572,13 @@ gb_internal void lb_build_switch_stmt(lbProcedure *p, AstSwitchStmt *ss, Scope *
lb_push_target_list(p, ss->label, done, nullptr, default_fall);
lb_open_scope(p, default_block->scope);
lb_build_stmt_list(p, default_stmts);
lb_close_scope(p, lbDeferExit_Default, default_block);
lb_close_scope(p, lbDeferExit_Default, default_block, default_clause);
lb_pop_target_list(p);
}
lb_emit_jump(p, done);
lb_start_block(p, done);
lb_close_scope(p, lbDeferExit_Default, done);
lb_close_scope(p, lbDeferExit_Default, done, ss->body);
}
gb_internal void lb_store_type_case_implicit(lbProcedure *p, Ast *clause, lbValue value, bool is_default_case) {
@@ -1627,7 +1629,7 @@ gb_internal void lb_type_case_body(lbProcedure *p, Ast *label, Ast *clause, lbBl
lb_push_target_list(p, label, done, nullptr, nullptr);
lb_build_stmt_list(p, cc->stmts);
lb_close_scope(p, lbDeferExit_Default, body);
lb_close_scope(p, lbDeferExit_Default, body, clause);
lb_pop_target_list(p);
lb_emit_jump(p, done);
@@ -1835,7 +1837,7 @@ gb_internal void lb_build_type_switch_stmt(lbProcedure *p, AstTypeSwitchStmt *ss
lb_emit_jump(p, done);
lb_start_block(p, done);
lb_close_scope(p, lbDeferExit_Default, done);
lb_close_scope(p, lbDeferExit_Default, done, ss->body);
}
@@ -1959,7 +1961,7 @@ gb_internal void lb_build_assignment(lbProcedure *p, Array<lbAddr> &lvals, Slice
p->in_multi_assignment = prev_in_assignment;
}
gb_internal void lb_build_return_stmt_internal(lbProcedure *p, lbValue res) {
gb_internal void lb_build_return_stmt_internal(lbProcedure *p, lbValue res, TokenPos pos) {
lbFunctionType *ft = lb_get_function_type(p->module, p->type);
bool return_by_pointer = ft->ret.kind == lbArg_Indirect;
bool split_returns = ft->multiple_return_original_type != nullptr;
@@ -1982,7 +1984,7 @@ gb_internal void lb_build_return_stmt_internal(lbProcedure *p, lbValue res) {
LLVMBuildStore(p->builder, LLVMConstNull(p->abi_function_type->ret.type), p->return_ptr.addr.value);
}
lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr);
lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr, pos);
// Check for terminator in the defer stmts
LLVMValueRef instr = LLVMGetLastInstruction(p->curr_block->block);
@@ -2012,7 +2014,7 @@ gb_internal void lb_build_return_stmt_internal(lbProcedure *p, lbValue res) {
ret_val = OdinLLVMBuildTransmute(p, ret_val, ret_type);
}
lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr);
lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr, pos);
// Check for terminator in the defer stmts
LLVMValueRef instr = LLVMGetLastInstruction(p->curr_block->block);
@@ -2021,7 +2023,7 @@ gb_internal void lb_build_return_stmt_internal(lbProcedure *p, lbValue res) {
}
}
}
gb_internal void lb_build_return_stmt(lbProcedure *p, Slice<Ast *> const &return_results) {
gb_internal void lb_build_return_stmt(lbProcedure *p, Slice<Ast *> const &return_results, TokenPos pos) {
lb_ensure_abi_function_type(p->module, p);
isize return_count = p->type->Proc.result_count;
@@ -2029,7 +2031,7 @@ gb_internal void lb_build_return_stmt(lbProcedure *p, Slice<Ast *> const &return
if (return_count == 0) {
// No return values
lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr);
lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr, pos);
// Check for terminator in the defer stmts
LLVMValueRef instr = LLVMGetLastInstruction(p->curr_block->block);
@@ -2138,11 +2140,11 @@ gb_internal void lb_build_return_stmt(lbProcedure *p, Slice<Ast *> const &return
GB_ASSERT(result_values.count-1 == result_eps.count);
lb_addr_store(p, p->return_ptr, result_values[result_values.count-1]);
lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr);
lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr, pos);
LLVMBuildRetVoid(p->builder);
return;
} else {
return lb_build_return_stmt_internal(p, result_values[result_values.count-1]);
return lb_build_return_stmt_internal(p, result_values[result_values.count-1], pos);
}
} else {
@@ -2169,7 +2171,7 @@ gb_internal void lb_build_return_stmt(lbProcedure *p, Slice<Ast *> const &return
}
if (return_by_pointer) {
lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr);
lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr, pos);
LLVMBuildRetVoid(p->builder);
return;
}
@@ -2177,13 +2179,13 @@ gb_internal void lb_build_return_stmt(lbProcedure *p, Slice<Ast *> const &return
res = lb_emit_load(p, res);
}
}
lb_build_return_stmt_internal(p, res);
lb_build_return_stmt_internal(p, res, pos);
}
gb_internal void lb_build_if_stmt(lbProcedure *p, Ast *node) {
ast_node(is, IfStmt, node);
lb_open_scope(p, is->scope); // Scope #1
defer (lb_close_scope(p, lbDeferExit_Default, nullptr));
defer (lb_close_scope(p, lbDeferExit_Default, nullptr, node));
lbBlock *then = lb_create_block(p, "if.then");
lbBlock *done = lb_create_block(p, "if.done");
@@ -2234,7 +2236,7 @@ gb_internal void lb_build_if_stmt(lbProcedure *p, Ast *node) {
lb_open_scope(p, scope_of_node(is->else_stmt));
lb_build_stmt(p, is->else_stmt);
lb_close_scope(p, lbDeferExit_Default, nullptr);
lb_close_scope(p, lbDeferExit_Default, nullptr, is->else_stmt);
}
lb_emit_jump(p, done);
@@ -2251,7 +2253,7 @@ gb_internal void lb_build_if_stmt(lbProcedure *p, Ast *node) {
lb_open_scope(p, scope_of_node(is->else_stmt));
lb_build_stmt(p, is->else_stmt);
lb_close_scope(p, lbDeferExit_Default, nullptr);
lb_close_scope(p, lbDeferExit_Default, nullptr, is->else_stmt);
lb_emit_jump(p, done);
}
@@ -2322,7 +2324,7 @@ gb_internal void lb_build_for_stmt(lbProcedure *p, Ast *node) {
}
lb_start_block(p, done);
lb_close_scope(p, lbDeferExit_Default, nullptr);
lb_close_scope(p, lbDeferExit_Default, nullptr, node);
}
gb_internal void lb_build_assign_stmt_array(lbProcedure *p, TokenKind op, lbAddr const &lhs, lbValue const &value) {
@@ -2652,7 +2654,7 @@ gb_internal void lb_build_stmt(lbProcedure *p, Ast *node) {
lb_open_scope(p, bs->scope);
lb_build_stmt_list(p, bs->stmts);
lb_close_scope(p, lbDeferExit_Default, nullptr);
lb_close_scope(p, lbDeferExit_Default, nullptr, node);
if (done != nullptr) {
lb_emit_jump(p, done);
@@ -2766,7 +2768,7 @@ gb_internal void lb_build_stmt(lbProcedure *p, Ast *node) {
case_end;
case_ast_node(rs, ReturnStmt, node);
lb_build_return_stmt(p, rs->results);
lb_build_return_stmt(p, rs->results, ast_token(node).pos);
case_end;
case_ast_node(is, IfStmt, node);
@@ -2819,7 +2821,7 @@ gb_internal void lb_build_stmt(lbProcedure *p, Ast *node) {
}
}
if (block != nullptr) {
lb_emit_defer_stmts(p, lbDeferExit_Branch, block);
lb_emit_defer_stmts(p, lbDeferExit_Branch, block, node);
}
lb_emit_jump(p, block);
lb_start_block(p, lb_create_block(p, "unreachable"));
@@ -2859,7 +2861,13 @@ gb_internal void lb_build_defer_stmt(lbProcedure *p, lbDefer const &d) {
}
}
gb_internal void lb_emit_defer_stmts(lbProcedure *p, lbDeferExitKind kind, lbBlock *block) {
gb_internal void lb_emit_defer_stmts(lbProcedure *p, lbDeferExitKind kind, lbBlock *block, TokenPos pos) {
TokenPos prev_token_pos = p->branch_location_pos;
if (p->uses_branch_location) {
p->branch_location_pos = pos;
}
defer (p->branch_location_pos = prev_token_pos);
isize count = p->defer_stmts.count;
isize i = count;
while (i --> 0) {
@@ -2886,6 +2894,21 @@ gb_internal void lb_emit_defer_stmts(lbProcedure *p, lbDeferExitKind kind, lbBlo
}
}
gb_internal void lb_emit_defer_stmts(lbProcedure *p, lbDeferExitKind kind, lbBlock *block, Ast *node) {
TokenPos pos = {};
if (node) {
if (node->kind == Ast_BlockStmt) {
pos = ast_end_token(node).pos;
} else if (node->kind == Ast_CaseClause) {
pos = ast_end_token(node).pos;
} else {
pos = ast_token(node).pos;
}
}
return lb_emit_defer_stmts(p, kind, block, pos);
}
gb_internal void lb_add_defer_node(lbProcedure *p, isize scope_index, Ast *stmt) {
Type *pt = base_type(p->type);
GB_ASSERT(pt->kind == Type_Proc);
+20 -7
View File
@@ -476,8 +476,8 @@ gb_internal lbValue lb_emit_or_else(lbProcedure *p, Ast *arg, Ast *else_expr, Ty
}
}
gb_internal void lb_build_return_stmt(lbProcedure *p, Slice<Ast *> const &return_results);
gb_internal void lb_build_return_stmt_internal(lbProcedure *p, lbValue res);
gb_internal void lb_build_return_stmt(lbProcedure *p, Slice<Ast *> const &return_results, TokenPos pos);
gb_internal void lb_build_return_stmt_internal(lbProcedure *p, lbValue res, TokenPos pos);
gb_internal lbValue lb_emit_or_return(lbProcedure *p, Ast *arg, TypeAndValue const &tv) {
lbValue lhs = {};
@@ -506,10 +506,10 @@ gb_internal lbValue lb_emit_or_return(lbProcedure *p, Ast *arg, TypeAndValue con
lbValue found = map_must_get(&p->module->values, end_entity);
lb_emit_store(p, found, rhs);
lb_build_return_stmt(p, {});
lb_build_return_stmt(p, {}, ast_token(arg).pos);
} else {
GB_ASSERT(tuple->variables.count == 1);
lb_build_return_stmt_internal(p, rhs);
lb_build_return_stmt_internal(p, rhs, ast_token(arg).pos);
}
}
lb_start_block(p, continue_block);
@@ -1200,9 +1200,22 @@ gb_internal lbValue lb_emit_struct_ep(lbProcedure *p, lbValue s, i32 index) {
lbValue gep = lb_emit_struct_ep_internal(p, s, index, result_type);
Type *bt = base_type(t);
if (bt->kind == Type_Struct && bt->Struct.is_packed) {
lb_set_metadata_custom_u64(p->module, gep.value, ODIN_METADATA_IS_PACKED, 1);
GB_ASSERT(lb_get_metadata_custom_u64(p->module, gep.value, ODIN_METADATA_IS_PACKED) == 1);
if (bt->kind == Type_Struct) {
if (bt->Struct.is_packed) {
lb_set_metadata_custom_u64(p->module, gep.value, ODIN_METADATA_IS_PACKED, 1);
GB_ASSERT(lb_get_metadata_custom_u64(p->module, gep.value, ODIN_METADATA_IS_PACKED) == 1);
}
u64 align_max = bt->Struct.custom_max_field_align;
u64 align_min = bt->Struct.custom_min_field_align;
GB_ASSERT(align_min == 0 || align_max == 0 || align_min <= align_max);
if (align_max) {
lb_set_metadata_custom_u64(p->module, gep.value, ODIN_METADATA_MAX_ALIGN, align_max);
GB_ASSERT(lb_get_metadata_custom_u64(p->module, gep.value, ODIN_METADATA_MAX_ALIGN) == align_max);
}
if (align_min) {
lb_set_metadata_custom_u64(p->module, gep.value, ODIN_METADATA_MIN_ALIGN, align_min);
GB_ASSERT(lb_get_metadata_custom_u64(p->module, gep.value, ODIN_METADATA_MIN_ALIGN) == align_min);
}
}
return gep;
+3 -3
View File
@@ -1192,7 +1192,7 @@ gb_internal bool parse_build_flags(Array<String> args) {
build_context.no_type_assert = true;
break;
case BuildFlag_NoDynamicLiterals:
build_context.no_dynamic_literals = true;
gb_printf_err("Warning: Use of -no-dynamic-literals is now redundant\n");
break;
case BuildFlag_NoCRT:
build_context.no_crt = true;
@@ -2120,7 +2120,7 @@ gb_internal void export_dependencies(Checker *c) {
for_array(i, files) {
AstFile *file = files[i];
gb_fprintf(&f, "\t\t\"%.*s\"", LIT(file->fullpath));
if (i+1 == files.count) {
if (i+1 < files.count) {
gb_fprintf(&f, ",");
}
gb_fprintf(&f, "\n");
@@ -2133,7 +2133,7 @@ gb_internal void export_dependencies(Checker *c) {
for_array(i, load_files) {
LoadFileCache *cache = load_files[i];
gb_fprintf(&f, "\t\t\"%.*s\"", LIT(cache->path));
if (i+1 == load_files.count) {
if (i+1 < load_files.count) {
gb_fprintf(&f, ",");
}
gb_fprintf(&f, "\n");
+67 -3
View File
@@ -6303,10 +6303,16 @@ gb_internal u64 parse_vet_tag(Token token_for_pos, String s) {
syntax_error(token_for_pos, "Invalid vet flag name: %.*s", LIT(p));
error_line("\tExpected one of the following\n");
error_line("\tunused\n");
error_line("\tunused-variables\n");
error_line("\tunused-imports\n");
error_line("\tunused-procedures\n");
error_line("\tshadowing\n");
error_line("\tusing-stmt\n");
error_line("\tusing-param\n");
error_line("\tstyle\n");
error_line("\textra\n");
error_line("\tcast\n");
error_line("\ttabs\n");
return build_context.vet_flags;
}
}
@@ -6324,6 +6330,63 @@ gb_internal u64 parse_vet_tag(Token token_for_pos, String s) {
return vet_flags &~ vet_not_flags;
}
gb_internal u64 parse_feature_tag(Token token_for_pos, String s) {
String const prefix = str_lit("feature");
GB_ASSERT(string_starts_with(s, prefix));
s = string_trim_whitespace(substring(s, prefix.len, s.len));
if (s.len == 0) {
return OptInFeatureFlag_NONE;
}
u64 feature_flags = 0;
u64 feature_not_flags = 0;
while (s.len > 0) {
String p = string_trim_whitespace(vet_tag_get_token(s, &s));
if (p.len == 0) {
break;
}
bool is_notted = false;
if (p[0] == '!') {
is_notted = true;
p = substring(p, 1, p.len);
if (p.len == 0) {
syntax_error(token_for_pos, "Expected a feature flag name after '!'");
return OptInFeatureFlag_NONE;
}
}
u64 flag = get_feature_flag_from_name(p);
if (flag != OptInFeatureFlag_NONE) {
if (is_notted) {
feature_not_flags |= flag;
} else {
feature_flags |= flag;
}
} else {
ERROR_BLOCK();
syntax_error(token_for_pos, "Invalid feature flag name: %.*s", LIT(p));
error_line("\tExpected one of the following\n");
error_line("\tdynamic-literals\n");
return OptInFeatureFlag_NONE;
}
}
if (feature_flags == 0 && feature_not_flags == 0) {
return OptInFeatureFlag_NONE;
}
if (feature_flags == 0 && feature_not_flags != 0) {
return OptInFeatureFlag_NONE &~ feature_not_flags;
}
if (feature_flags != 0 && feature_not_flags == 0) {
return feature_flags;
}
GB_ASSERT(feature_flags != 0 && feature_not_flags != 0);
return feature_flags &~ feature_not_flags;
}
gb_internal String dir_from_path(String path) {
String base_dir = path;
for (isize i = path.len-1; i >= 0; i--) {
@@ -6437,6 +6500,9 @@ gb_internal bool parse_file_tag(const String &lc, const Token &tok, AstFile *f)
} else if (command == "file") {
f->flags |= AstFile_IsPrivateFile;
}
} else if (string_starts_with(lc, str_lit("feature"))) {
f->feature_flags |= parse_feature_tag(tok, lc);
f->feature_flags_set = true;
} else if (lc == "lazy") {
if (build_context.ignore_lazy) {
// Ignore
@@ -6531,9 +6597,7 @@ gb_internal bool parse_file(Parser *p, AstFile *f) {
}
f->package_name = package_name.string;
// TODO: Shouldn't single file only matter for build tags? no-instrumentation for example
// should be respected even when in single file mode.
if (!f->pkg->is_single_file) {
{
if (docs != nullptr && docs->list.count > 0) {
for (Token const &tok : docs->list) {
GB_ASSERT(tok.kind == Token_Comment);
+2
View File
@@ -108,7 +108,9 @@ struct AstFile {
String package_name;
u64 vet_flags;
u64 feature_flags;
bool vet_flags_set;
bool feature_flags_set;
// >= 0: In Expression
// < 0: In Control Clause