mirror of
https://github.com/Ed94/Odin.git
synced 2026-07-17 00:11:25 -07:00
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
+35
-3
@@ -323,6 +323,7 @@ struct BuildContext {
|
||||
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;
|
||||
|
||||
@@ -422,6 +423,7 @@ struct BuildContext {
|
||||
Array<String> extra_packages;
|
||||
|
||||
StringSet test_names;
|
||||
bool test_all_packages;
|
||||
|
||||
gbAffinity affinity;
|
||||
isize thread_count;
|
||||
@@ -1161,7 +1163,27 @@ gb_internal String get_fullpath_relative(gbAllocator a, String base_dir, String
|
||||
}
|
||||
|
||||
|
||||
gb_internal String get_fullpath_core(gbAllocator a, String path) {
|
||||
gb_internal String get_fullpath_base_collection(gbAllocator a, String path) {
|
||||
String module_dir = odin_root_dir();
|
||||
|
||||
String base = str_lit("base/");
|
||||
|
||||
isize str_len = module_dir.len + base.len + path.len;
|
||||
u8 *str = gb_alloc_array(heap_allocator(), u8, str_len+1);
|
||||
defer (gb_free(heap_allocator(), str));
|
||||
|
||||
isize i = 0;
|
||||
gb_memmove(str+i, module_dir.text, module_dir.len); i += module_dir.len;
|
||||
gb_memmove(str+i, base.text, base.len); i += base.len;
|
||||
gb_memmove(str+i, path.text, path.len); i += path.len;
|
||||
str[i] = 0;
|
||||
|
||||
String res = make_string(str, i);
|
||||
res = string_trim_whitespace(res);
|
||||
return path_to_fullpath(a, res);
|
||||
}
|
||||
|
||||
gb_internal String get_fullpath_core_collection(gbAllocator a, String path) {
|
||||
String module_dir = odin_root_dir();
|
||||
|
||||
String core = str_lit("core/");
|
||||
@@ -1454,6 +1476,16 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (bc->metrics.os == TargetOs_freestanding) {
|
||||
bc->ODIN_DEFAULT_TO_NIL_ALLOCATOR = !bc->ODIN_DEFAULT_TO_PANIC_ALLOCATOR;
|
||||
} else if (is_arch_wasm()) {
|
||||
if (bc->metrics.os == TargetOs_js || bc->metrics.os == TargetOs_wasi) {
|
||||
// TODO(bill): Should these even have a default "heap-like" allocator?
|
||||
}
|
||||
bc->ODIN_DEFAULT_TO_PANIC_ALLOCATOR = true;
|
||||
bc->ODIN_DEFAULT_TO_NIL_ALLOCATOR = !bc->ODIN_DEFAULT_TO_PANIC_ALLOCATOR;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(GB_SYSTEM_WINDOWS)
|
||||
@@ -1588,8 +1620,8 @@ gb_internal bool init_build_paths(String init_filename) {
|
||||
produces_output_file = true;
|
||||
}
|
||||
|
||||
|
||||
if (build_context.ODIN_DEFAULT_TO_NIL_ALLOCATOR) {
|
||||
if (build_context.ODIN_DEFAULT_TO_NIL_ALLOCATOR ||
|
||||
build_context.ODIN_DEFAULT_TO_PANIC_ALLOCATOR) {
|
||||
bc->no_dynamic_literals = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -4892,8 +4892,10 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As
|
||||
switch (bt->kind) {
|
||||
case Type_Basic:
|
||||
switch (bt->Basic.kind) {
|
||||
case Basic_complex32: operand->type = t_f16; break;
|
||||
case Basic_complex64: operand->type = t_f32; break;
|
||||
case Basic_complex128: operand->type = t_f64; break;
|
||||
case Basic_quaternion64: operand->type = t_f16; break;
|
||||
case Basic_quaternion128: operand->type = t_f32; break;
|
||||
case Basic_quaternion256: operand->type = t_f64; break;
|
||||
}
|
||||
|
||||
+2
-2
@@ -1143,7 +1143,7 @@ gb_internal void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) {
|
||||
"\tat %s",
|
||||
LIT(name), token_pos_to_string(pos));
|
||||
}
|
||||
} else if (!are_types_identical(this_type, other_type)) {
|
||||
} 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",
|
||||
@@ -1284,7 +1284,7 @@ gb_internal void check_global_variable_decl(CheckerContext *ctx, Entity *&e, Ast
|
||||
TokenPos pos = f->token.pos;
|
||||
Type *this_type = base_type(e->type);
|
||||
Type *other_type = base_type(f->type);
|
||||
if (!are_types_identical(this_type, other_type)) {
|
||||
if (!signature_parameter_similar_enough(this_type, other_type)) {
|
||||
error(e->token,
|
||||
"Foreign entity '%.*s' previously declared elsewhere with a different type\n"
|
||||
"\tat %s",
|
||||
|
||||
+57
-7
@@ -2988,6 +2988,13 @@ gb_internal bool check_is_castable_to(CheckerContext *c, Operand *operand, Type
|
||||
}
|
||||
// proc <-> proc
|
||||
if (is_type_proc(src) && is_type_proc(dst)) {
|
||||
if (is_type_polymorphic(dst)) {
|
||||
if (is_type_polymorphic(src) &&
|
||||
operand->mode == Addressing_Variable) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -3067,7 +3074,6 @@ gb_internal void check_cast(CheckerContext *c, Operand *x, Type *type) {
|
||||
|
||||
bool is_const_expr = x->mode == Addressing_Constant;
|
||||
bool can_convert = check_cast_internal(c, x, type);
|
||||
|
||||
if (!can_convert) {
|
||||
TEMPORARY_ALLOCATOR_GUARD();
|
||||
gbString expr_str = expr_to_string(x->expr, temporary_allocator());
|
||||
@@ -3108,6 +3114,25 @@ gb_internal void check_cast(CheckerContext *c, Operand *x, Type *type) {
|
||||
final_type = default_type(x->type);
|
||||
}
|
||||
update_untyped_expr_type(c, x->expr, final_type, true);
|
||||
} else {
|
||||
Type *src = core_type(x->type);
|
||||
Type *dst = core_type(type);
|
||||
if (src != dst) {
|
||||
if (is_type_integer_128bit(src) && is_type_float(dst)) {
|
||||
add_package_dependency(c, "runtime", "floattidf_unsigned");
|
||||
add_package_dependency(c, "runtime", "floattidf");
|
||||
} else if (is_type_integer_128bit(dst) && is_type_float(src)) {
|
||||
add_package_dependency(c, "runtime", "fixunsdfti");
|
||||
add_package_dependency(c, "runtime", "fixunsdfdi");
|
||||
} else if (src == t_f16 && is_type_float(dst)) {
|
||||
add_package_dependency(c, "runtime", "gnu_h2f_ieee");
|
||||
add_package_dependency(c, "runtime", "extendhfsf2");
|
||||
} else if (is_type_float(dst) && dst == t_f16) {
|
||||
add_package_dependency(c, "runtime", "truncsfhf2");
|
||||
add_package_dependency(c, "runtime", "truncdfhf2");
|
||||
add_package_dependency(c, "runtime", "gnu_f2h_ieee");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
x->type = type;
|
||||
@@ -3728,9 +3753,14 @@ gb_internal void check_binary_expr(CheckerContext *c, Operand *x, Ast *node, Typ
|
||||
x->mode = Addressing_Invalid;
|
||||
return;
|
||||
}
|
||||
|
||||
if (op.kind == Token_Quo || op.kind == Token_QuoEq) {
|
||||
Type *bt = base_type(x->type);
|
||||
Type *bt = base_type(x->type);
|
||||
if (op.kind == Token_Mod || op.kind == Token_ModEq ||
|
||||
op.kind == Token_ModMod || op.kind == Token_ModModEq) {
|
||||
if (bt->kind == Type_Basic) switch (bt->Basic.kind) {
|
||||
case Basic_u128: add_package_dependency(c, "runtime", "umodti3"); break;
|
||||
case Basic_i128: add_package_dependency(c, "runtime", "modti3"); break;
|
||||
}
|
||||
} else if (op.kind == Token_Quo || op.kind == Token_QuoEq) {
|
||||
if (bt->kind == Type_Basic) switch (bt->Basic.kind) {
|
||||
case Basic_complex32: add_package_dependency(c, "runtime", "quo_complex32"); break;
|
||||
case Basic_complex64: add_package_dependency(c, "runtime", "quo_complex64"); break;
|
||||
@@ -3738,13 +3768,32 @@ gb_internal void check_binary_expr(CheckerContext *c, Operand *x, Ast *node, Typ
|
||||
case Basic_quaternion64: add_package_dependency(c, "runtime", "quo_quaternion64"); break;
|
||||
case Basic_quaternion128: add_package_dependency(c, "runtime", "quo_quaternion128"); break;
|
||||
case Basic_quaternion256: add_package_dependency(c, "runtime", "quo_quaternion256"); break;
|
||||
|
||||
case Basic_u128: add_package_dependency(c, "runtime", "udivti3"); break;
|
||||
case Basic_i128: add_package_dependency(c, "runtime", "divti3"); break;
|
||||
}
|
||||
} else if (op.kind == Token_Mul || op.kind == Token_MulEq) {
|
||||
Type *bt = base_type(x->type);
|
||||
if (bt->kind == Type_Basic) switch (bt->Basic.kind) {
|
||||
case Basic_quaternion64: add_package_dependency(c, "runtime", "mul_quaternion64"); break;
|
||||
case Basic_quaternion64: add_package_dependency(c, "runtime", "mul_quaternion64"); break;
|
||||
case Basic_quaternion128: add_package_dependency(c, "runtime", "mul_quaternion128"); break;
|
||||
case Basic_quaternion256: add_package_dependency(c, "runtime", "mul_quaternion256"); break;
|
||||
|
||||
|
||||
case Basic_u128:
|
||||
case Basic_i128:
|
||||
if (is_arch_wasm()) {
|
||||
add_package_dependency(c, "runtime", "__multi3");
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else if (op.kind == Token_Shl || op.kind == Token_ShlEq) {
|
||||
if (bt->kind == Type_Basic) switch (bt->Basic.kind) {
|
||||
case Basic_u128:
|
||||
case Basic_i128:
|
||||
if (is_arch_wasm()) {
|
||||
add_package_dependency(c, "runtime", "__ashlti3");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4575,7 +4624,8 @@ gb_internal bool is_entity_declared_for_selector(Entity *entity, Scope *import_s
|
||||
if (entity->kind == Entity_Builtin) {
|
||||
// NOTE(bill): Builtin's are in the universal scope which is part of every scopes hierarchy
|
||||
// This means that we should just ignore the found result through it
|
||||
*allow_builtin = entity->scope == import_scope || entity->scope != builtin_pkg->scope;
|
||||
*allow_builtin = entity->scope == import_scope ||
|
||||
(entity->scope != builtin_pkg->scope && entity->scope != intrinsics_pkg->scope);
|
||||
} else if ((entity->scope->flags&ScopeFlag_Global) == ScopeFlag_Global && (import_scope->flags&ScopeFlag_Global) == 0) {
|
||||
is_declared = false;
|
||||
}
|
||||
|
||||
+1
-1
@@ -1934,7 +1934,7 @@ gb_internal void check_value_decl_stmt(CheckerContext *ctx, Ast *node, u32 mod_f
|
||||
TokenPos pos = f->token.pos;
|
||||
Type *this_type = base_type(e->type);
|
||||
Type *other_type = base_type(f->type);
|
||||
if (!are_types_identical(this_type, other_type)) {
|
||||
if (!signature_parameter_similar_enough(this_type, other_type)) {
|
||||
error(e->token,
|
||||
"Foreign entity '%.*s' previously declared elsewhere with a different type\n"
|
||||
"\tat %s",
|
||||
|
||||
+27
-17
@@ -219,13 +219,13 @@ gb_internal void check_struct_fields(CheckerContext *ctx, Ast *node, Slice<Entit
|
||||
}
|
||||
|
||||
|
||||
gb_internal bool check_custom_align(CheckerContext *ctx, Ast *node, i64 *align_) {
|
||||
gb_internal bool check_custom_align(CheckerContext *ctx, Ast *node, i64 *align_, char const *msg) {
|
||||
GB_ASSERT(align_ != nullptr);
|
||||
Operand o = {};
|
||||
check_expr(ctx, &o, node);
|
||||
if (o.mode != Addressing_Constant) {
|
||||
if (o.mode != Addressing_Invalid) {
|
||||
error(node, "#align must be a constant");
|
||||
error(node, "#%s must be a constant", msg);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -237,13 +237,13 @@ gb_internal bool check_custom_align(CheckerContext *ctx, Ast *node, i64 *align_)
|
||||
if (v.used > 1) {
|
||||
gbAllocator a = heap_allocator();
|
||||
String str = big_int_to_string(a, &v);
|
||||
error(node, "#align too large, %.*s", LIT(str));
|
||||
error(node, "#%s too large, %.*s", msg, LIT(str));
|
||||
gb_free(a, str.text);
|
||||
return false;
|
||||
}
|
||||
i64 align = big_int_to_i64(&v);
|
||||
if (align < 1 || !gb_is_power_of_two(cast(isize)align)) {
|
||||
error(node, "#align must be a power of 2, got %lld", align);
|
||||
error(node, "#%s must be a power of 2, got %lld", msg, align);
|
||||
return false;
|
||||
}
|
||||
*align_ = align;
|
||||
@@ -251,7 +251,7 @@ gb_internal bool check_custom_align(CheckerContext *ctx, Ast *node, i64 *align_)
|
||||
}
|
||||
}
|
||||
|
||||
error(node, "#align must be an integer");
|
||||
error(node, "#%s must be an integer", msg);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -645,16 +645,26 @@ gb_internal void check_struct_type(CheckerContext *ctx, Type *struct_type, Ast *
|
||||
check_struct_fields(ctx, node, &struct_type->Struct.fields, &struct_type->Struct.tags, st->fields, min_field_count, struct_type, context);
|
||||
}
|
||||
|
||||
if (st->align != nullptr) {
|
||||
if (st->is_packed) {
|
||||
syntax_error(st->align, "'#align' cannot be applied with '#packed'");
|
||||
return;
|
||||
}
|
||||
i64 custom_align = 1;
|
||||
if (check_custom_align(ctx, st->align, &custom_align)) {
|
||||
struct_type->Struct.custom_align = custom_align;
|
||||
}
|
||||
#define ST_ALIGN(_name) if (st->_name != nullptr) { \
|
||||
if (st->is_packed) { \
|
||||
syntax_error(st->_name, "'#%s' cannot be applied with '#packed'", #_name); \
|
||||
return; \
|
||||
} \
|
||||
i64 align = 1; \
|
||||
if (check_custom_align(ctx, st->_name, &align, #_name)) { \
|
||||
struct_type->Struct.custom_##_name = align; \
|
||||
} \
|
||||
}
|
||||
|
||||
ST_ALIGN(field_align);
|
||||
ST_ALIGN(align);
|
||||
if (struct_type->Struct.custom_align < struct_type->Struct.custom_field_align) {
|
||||
warning(st->align, "#align(%lld) is defined to be less than #field_name(%lld)",
|
||||
cast(long long)struct_type->Struct.custom_align,
|
||||
cast(long long)struct_type->Struct.custom_field_align);
|
||||
}
|
||||
|
||||
#undef ST_ALIGN
|
||||
}
|
||||
gb_internal void check_union_type(CheckerContext *ctx, Type *union_type, Ast *node, Array<Operand> *poly_operands, Type *named_type, Type *original_type_for_poly) {
|
||||
GB_ASSERT(is_type_union(union_type));
|
||||
@@ -746,7 +756,7 @@ gb_internal void check_union_type(CheckerContext *ctx, Type *union_type, Ast *no
|
||||
|
||||
if (ut->align != nullptr) {
|
||||
i64 custom_align = 1;
|
||||
if (check_custom_align(ctx, ut->align, &custom_align)) {
|
||||
if (check_custom_align(ctx, ut->align, &custom_align, "align")) {
|
||||
if (variants.count == 0) {
|
||||
error(ut->align, "An empty union cannot have a custom alignment");
|
||||
} else {
|
||||
@@ -2380,7 +2390,7 @@ gb_internal Type *make_soa_struct_internal(CheckerContext *ctx, Ast *array_typ_e
|
||||
|
||||
bool is_polymorphic = is_type_polymorphic(elem);
|
||||
|
||||
if ((!is_polymorphic || soa_kind == StructSoa_Fixed) && !is_type_struct(elem) && !is_type_raw_union(elem) && !(is_type_array(elem) && bt_elem->Array.count <= 4)) {
|
||||
if (!is_polymorphic && !is_type_struct(elem) && !is_type_raw_union(elem) && !(is_type_array(elem) && bt_elem->Array.count <= 4)) {
|
||||
gbString str = type_to_string(elem);
|
||||
error(elem_expr, "Invalid type for an #soa array, expected a struct or array of length 4 or below, got '%s'", str);
|
||||
gb_string_free(str);
|
||||
@@ -2397,7 +2407,7 @@ gb_internal Type *make_soa_struct_internal(CheckerContext *ctx, Ast *array_typ_e
|
||||
case StructSoa_Slice: extra_field_count = 1; break;
|
||||
case StructSoa_Dynamic: extra_field_count = 3; break;
|
||||
}
|
||||
if (is_polymorphic && soa_kind != StructSoa_Fixed) {
|
||||
if (is_polymorphic) {
|
||||
field_count = 0;
|
||||
|
||||
soa_struct = alloc_type_struct();
|
||||
|
||||
+112
-75
@@ -770,15 +770,17 @@ gb_internal void add_type_info_dependency(CheckerInfo *info, DeclInfo *d, Type *
|
||||
rw_mutex_unlock(&d->type_info_deps_mutex);
|
||||
}
|
||||
|
||||
gb_internal AstPackage *get_core_package(CheckerInfo *info, String name) {
|
||||
|
||||
gb_internal AstPackage *get_runtime_package(CheckerInfo *info) {
|
||||
String name = str_lit("runtime");
|
||||
gbAllocator a = heap_allocator();
|
||||
String path = get_fullpath_core(a, name);
|
||||
String path = get_fullpath_base_collection(a, name);
|
||||
defer (gb_free(a, path.text));
|
||||
auto found = string_map_get(&info->packages, path);
|
||||
if (found == nullptr) {
|
||||
gb_printf_err("Name: %.*s\n", LIT(name));
|
||||
gb_printf_err("Fullpath: %.*s\n", LIT(path));
|
||||
|
||||
|
||||
for (auto const &entry : info->packages) {
|
||||
gb_printf_err("%.*s\n", LIT(entry.key));
|
||||
}
|
||||
@@ -787,6 +789,26 @@ gb_internal AstPackage *get_core_package(CheckerInfo *info, String name) {
|
||||
return *found;
|
||||
}
|
||||
|
||||
gb_internal AstPackage *get_core_package(CheckerInfo *info, String name) {
|
||||
if (name == "runtime") {
|
||||
return get_runtime_package(info);
|
||||
}
|
||||
|
||||
gbAllocator a = heap_allocator();
|
||||
String path = get_fullpath_core_collection(a, name);
|
||||
defer (gb_free(a, path.text));
|
||||
auto found = string_map_get(&info->packages, path);
|
||||
if (found == nullptr) {
|
||||
gb_printf_err("Name: %.*s\n", LIT(name));
|
||||
gb_printf_err("Fullpath: %.*s\n", LIT(path));
|
||||
|
||||
for (auto const &entry : info->packages) {
|
||||
gb_printf_err("%.*s\n", LIT(entry.key));
|
||||
}
|
||||
GB_ASSERT_MSG(found != nullptr, "Missing core package %.*s", LIT(name));
|
||||
}
|
||||
return *found;
|
||||
}
|
||||
|
||||
gb_internal void add_package_dependency(CheckerContext *c, char const *package_name, char const *name) {
|
||||
String n = make_string_c(name);
|
||||
@@ -1069,19 +1091,20 @@ gb_internal void init_universal(void) {
|
||||
}
|
||||
|
||||
|
||||
add_global_bool_constant("ODIN_DEBUG", bc->ODIN_DEBUG);
|
||||
add_global_bool_constant("ODIN_DISABLE_ASSERT", bc->ODIN_DISABLE_ASSERT);
|
||||
add_global_bool_constant("ODIN_DEFAULT_TO_NIL_ALLOCATOR", bc->ODIN_DEFAULT_TO_NIL_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);
|
||||
add_global_bool_constant("ODIN_NO_ENTRY_POINT", bc->no_entry_point);
|
||||
add_global_bool_constant("ODIN_FOREIGN_ERROR_PROCEDURES", bc->ODIN_FOREIGN_ERROR_PROCEDURES);
|
||||
add_global_bool_constant("ODIN_NO_RTTI", bc->no_rtti);
|
||||
add_global_bool_constant("ODIN_DEBUG", bc->ODIN_DEBUG);
|
||||
add_global_bool_constant("ODIN_DISABLE_ASSERT", bc->ODIN_DISABLE_ASSERT);
|
||||
add_global_bool_constant("ODIN_DEFAULT_TO_NIL_ALLOCATOR", bc->ODIN_DEFAULT_TO_NIL_ALLOCATOR);
|
||||
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);
|
||||
add_global_bool_constant("ODIN_NO_ENTRY_POINT", bc->no_entry_point);
|
||||
add_global_bool_constant("ODIN_FOREIGN_ERROR_PROCEDURES", bc->ODIN_FOREIGN_ERROR_PROCEDURES);
|
||||
add_global_bool_constant("ODIN_NO_RTTI", bc->no_rtti);
|
||||
|
||||
add_global_bool_constant("ODIN_VALGRIND_SUPPORT", bc->ODIN_VALGRIND_SUPPORT);
|
||||
add_global_bool_constant("ODIN_TILDE", bc->tilde_backend);
|
||||
add_global_bool_constant("ODIN_VALGRIND_SUPPORT", bc->ODIN_VALGRIND_SUPPORT);
|
||||
add_global_bool_constant("ODIN_TILDE", bc->tilde_backend);
|
||||
|
||||
add_global_constant("ODIN_COMPILE_TIMESTAMP", t_untyped_integer, exact_value_i64(odin_compile_timestamp()));
|
||||
|
||||
@@ -2345,6 +2368,43 @@ gb_internal void force_add_dependency_entity(Checker *c, Scope *scope, String co
|
||||
add_dependency_to_set(c, e);
|
||||
}
|
||||
|
||||
gb_internal void collect_testing_procedures_of_package(Checker *c, AstPackage *pkg) {
|
||||
AstPackage *testing_package = get_core_package(&c->info, str_lit("testing"));
|
||||
Scope *testing_scope = testing_package->scope;
|
||||
Entity *test_signature = scope_lookup_current(testing_scope, str_lit("Test_Signature"));
|
||||
|
||||
Scope *s = pkg->scope;
|
||||
for (auto const &entry : s->elements) {
|
||||
Entity *e = entry.value;
|
||||
if (e->kind != Entity_Procedure) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((e->flags & EntityFlag_Test) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String name = e->token.string;
|
||||
|
||||
bool is_tester = true;
|
||||
|
||||
Type *t = base_type(e->type);
|
||||
GB_ASSERT(t->kind == Type_Proc);
|
||||
if (are_types_identical(t, base_type(test_signature->type))) {
|
||||
// Good
|
||||
} else {
|
||||
gbString str = type_to_string(t);
|
||||
error(e->token, "Testing procedures must have a signature type of proc(^testing.T), got %s", str);
|
||||
gb_string_free(str);
|
||||
is_tester = false;
|
||||
}
|
||||
|
||||
if (is_tester) {
|
||||
add_dependency_to_set(c, e);
|
||||
array_add(&c->info.testing_procedures, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gb_internal void generate_minimum_dependency_set_internal(Checker *c, Entity *start) {
|
||||
for_array(i, c->info.definitions) {
|
||||
@@ -2448,41 +2508,13 @@ gb_internal void generate_minimum_dependency_set_internal(Checker *c, Entity *st
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Entity *test_signature = scope_lookup_current(testing_scope, str_lit("Test_Signature"));
|
||||
|
||||
|
||||
AstPackage *pkg = c->info.init_package;
|
||||
Scope *s = pkg->scope;
|
||||
collect_testing_procedures_of_package(c, pkg);
|
||||
|
||||
for (auto const &entry : s->elements) {
|
||||
Entity *e = entry.value;
|
||||
if (e->kind != Entity_Procedure) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((e->flags & EntityFlag_Test) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String name = e->token.string;
|
||||
|
||||
bool is_tester = true;
|
||||
|
||||
Type *t = base_type(e->type);
|
||||
GB_ASSERT(t->kind == Type_Proc);
|
||||
if (are_types_identical(t, base_type(test_signature->type))) {
|
||||
// Good
|
||||
} else {
|
||||
gbString str = type_to_string(t);
|
||||
error(e->token, "Testing procedures must have a signature type of proc(^testing.T), got %s", str);
|
||||
gb_string_free(str);
|
||||
is_tester = false;
|
||||
}
|
||||
|
||||
if (is_tester) {
|
||||
add_dependency_to_set(c, e);
|
||||
array_add(&c->info.testing_procedures, e);
|
||||
if (build_context.test_all_packages) {
|
||||
for (auto const &entry : c->info.packages) {
|
||||
AstPackage *pkg = entry.value;
|
||||
collect_testing_procedures_of_package(c, pkg);
|
||||
}
|
||||
}
|
||||
} else if (start != nullptr) {
|
||||
@@ -2517,13 +2549,11 @@ gb_internal void generate_minimum_dependency_set(Checker *c, Entity *start) {
|
||||
|
||||
// Odin internal procedures
|
||||
str_lit("__init_context"),
|
||||
str_lit("cstring_to_string"),
|
||||
// str_lit("cstring_to_string"),
|
||||
str_lit("_cleanup_runtime"),
|
||||
|
||||
// Pseudo-CRT required procedures
|
||||
str_lit("memset"),
|
||||
str_lit("memcpy"),
|
||||
str_lit("memmove"),
|
||||
|
||||
// Utility procedures
|
||||
str_lit("memory_equal"),
|
||||
@@ -2531,28 +2561,34 @@ gb_internal void generate_minimum_dependency_set(Checker *c, Entity *start) {
|
||||
str_lit("memory_compare_zero"),
|
||||
);
|
||||
|
||||
FORCE_ADD_RUNTIME_ENTITIES(!build_context.tilde_backend,
|
||||
// Extended data type internal procedures
|
||||
str_lit("umodti3"),
|
||||
str_lit("udivti3"),
|
||||
str_lit("modti3"),
|
||||
str_lit("divti3"),
|
||||
str_lit("fixdfti"),
|
||||
str_lit("fixunsdfti"),
|
||||
str_lit("fixunsdfdi"),
|
||||
str_lit("floattidf"),
|
||||
str_lit("floattidf_unsigned"),
|
||||
str_lit("truncsfhf2"),
|
||||
str_lit("truncdfhf2"),
|
||||
str_lit("gnu_h2f_ieee"),
|
||||
str_lit("gnu_f2h_ieee"),
|
||||
str_lit("extendhfsf2"),
|
||||
|
||||
// WASM Specific
|
||||
str_lit("__ashlti3"),
|
||||
str_lit("__multi3"),
|
||||
// Only required if no CRT is present
|
||||
FORCE_ADD_RUNTIME_ENTITIES(build_context.no_crt,
|
||||
str_lit("memcpy"),
|
||||
str_lit("memmove"),
|
||||
);
|
||||
|
||||
// FORCE_ADD_RUNTIME_ENTITIES(!build_context.tilde_backend,
|
||||
// // Extended data type internal procedures
|
||||
// str_lit("umodti3"),
|
||||
// str_lit("udivti3"),
|
||||
// str_lit("modti3"),
|
||||
// str_lit("divti3"),
|
||||
// str_lit("fixdfti"),
|
||||
// str_lit("fixunsdfti"),
|
||||
// str_lit("fixunsdfdi"),
|
||||
// str_lit("floattidf"),
|
||||
// str_lit("floattidf_unsigned"),
|
||||
// str_lit("truncsfhf2"),
|
||||
// str_lit("truncdfhf2"),
|
||||
// str_lit("gnu_h2f_ieee"),
|
||||
// str_lit("gnu_f2h_ieee"),
|
||||
// str_lit("extendhfsf2"),
|
||||
|
||||
// // WASM Specific
|
||||
// str_lit("__ashlti3"),
|
||||
// str_lit("__multi3"),
|
||||
// );
|
||||
|
||||
FORCE_ADD_RUNTIME_ENTITIES(!build_context.no_rtti,
|
||||
// Odin types
|
||||
str_lit("Type_Info"),
|
||||
@@ -3809,6 +3845,7 @@ gb_internal void check_builtin_attributes(CheckerContext *ctx, Entity *e, Array<
|
||||
case Entity_ProcGroup:
|
||||
case Entity_Procedure:
|
||||
case Entity_TypeName:
|
||||
case Entity_Constant:
|
||||
// Okay
|
||||
break;
|
||||
default:
|
||||
@@ -4551,10 +4588,10 @@ gb_internal Array<ImportPathItem> find_import_path(Checker *c, AstPackage *start
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pkg->kind == Package_Runtime) {
|
||||
// NOTE(bill): Allow cyclic imports within the runtime package for the time being
|
||||
continue;
|
||||
}
|
||||
// if (pkg->kind == Package_Runtime) {
|
||||
// // NOTE(bill): Allow cyclic imports within the runtime package for the time being
|
||||
// continue;
|
||||
// }
|
||||
|
||||
ImportPathItem item = {pkg, decl};
|
||||
if (pkg == end) {
|
||||
|
||||
@@ -34,11 +34,6 @@ enum BuiltinProcId {
|
||||
|
||||
BuiltinProc_soa_zip,
|
||||
BuiltinProc_soa_unzip,
|
||||
|
||||
BuiltinProc_transpose,
|
||||
BuiltinProc_outer_product,
|
||||
BuiltinProc_hadamard_product,
|
||||
BuiltinProc_matrix_flatten,
|
||||
|
||||
BuiltinProc_unreachable,
|
||||
|
||||
@@ -48,6 +43,11 @@ enum BuiltinProcId {
|
||||
|
||||
// "Intrinsics"
|
||||
BuiltinProc_is_package_imported,
|
||||
|
||||
BuiltinProc_transpose,
|
||||
BuiltinProc_outer_product,
|
||||
BuiltinProc_hadamard_product,
|
||||
BuiltinProc_matrix_flatten,
|
||||
|
||||
BuiltinProc_soa_struct,
|
||||
|
||||
@@ -341,11 +341,6 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = {
|
||||
|
||||
{STR_LIT("soa_zip"), 1, true, Expr_Expr, BuiltinProcPkg_builtin},
|
||||
{STR_LIT("soa_unzip"), 1, false, Expr_Expr, BuiltinProcPkg_builtin},
|
||||
|
||||
{STR_LIT("transpose"), 1, false, Expr_Expr, BuiltinProcPkg_builtin},
|
||||
{STR_LIT("outer_product"), 2, false, Expr_Expr, BuiltinProcPkg_builtin},
|
||||
{STR_LIT("hadamard_product"), 2, false, Expr_Expr, BuiltinProcPkg_builtin},
|
||||
{STR_LIT("matrix_flatten"), 1, false, Expr_Expr, BuiltinProcPkg_builtin},
|
||||
|
||||
{STR_LIT("unreachable"), 0, false, Expr_Expr, BuiltinProcPkg_builtin, /*diverging*/true},
|
||||
|
||||
@@ -356,6 +351,11 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = {
|
||||
|
||||
// "Intrinsics"
|
||||
{STR_LIT("is_package_imported"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
|
||||
{STR_LIT("transpose"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
{STR_LIT("outer_product"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
{STR_LIT("hadamard_product"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
{STR_LIT("matrix_flatten"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
|
||||
{STR_LIT("soa_struct"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, // Type
|
||||
|
||||
|
||||
@@ -1064,6 +1064,11 @@ gb_internal lbProcedure *lb_create_startup_type_info(lbModule *m) {
|
||||
LLVMSetLinkage(p->value, LLVMInternalLinkage);
|
||||
|
||||
lb_add_attribute_to_proc(m, p->value, "nounwind");
|
||||
// lb_add_attribute_to_proc(p->module, p->value, "mustprogress");
|
||||
// lb_add_attribute_to_proc(p->module, p->value, "nofree");
|
||||
// lb_add_attribute_to_proc(p->module, p->value, "norecurse");
|
||||
// lb_add_attribute_to_proc(p->module, p->value, "nosync");
|
||||
// lb_add_attribute_to_proc(p->module, p->value, "willreturn");
|
||||
if (!LB_USE_GIANT_PACKED_STRUCT) {
|
||||
lb_add_attribute_to_proc(m, p->value, "optnone");
|
||||
lb_add_attribute_to_proc(m, p->value, "noinline");
|
||||
|
||||
@@ -2033,9 +2033,9 @@ gb_internal lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValu
|
||||
|
||||
case BuiltinProc_clamp:
|
||||
return lb_emit_clamp(p, type_of_expr(expr),
|
||||
lb_build_expr(p, ce->args[0]),
|
||||
lb_build_expr(p, ce->args[1]),
|
||||
lb_build_expr(p, ce->args[2]));
|
||||
lb_build_expr(p, ce->args[0]),
|
||||
lb_build_expr(p, ce->args[1]),
|
||||
lb_build_expr(p, ce->args[2]));
|
||||
|
||||
|
||||
case BuiltinProc_soa_zip:
|
||||
|
||||
@@ -83,27 +83,13 @@ gb_internal LLVMValueRef lb_mem_zero_ptr_internal(lbProcedure *p, LLVMValueRef p
|
||||
lb_type(p->module, t_rawptr),
|
||||
lb_type(p->module, t_int)
|
||||
};
|
||||
if (true || is_inlinable) {
|
||||
LLVMValueRef args[4] = {};
|
||||
args[0] = LLVMBuildPointerCast(p->builder, ptr, types[0], "");
|
||||
args[1] = LLVMConstInt(LLVMInt8TypeInContext(p->module->ctx), 0, false);
|
||||
args[2] = LLVMBuildIntCast2(p->builder, len, types[1], /*signed*/false, "");
|
||||
args[3] = LLVMConstInt(LLVMInt1TypeInContext(p->module->ctx), is_volatile, false);
|
||||
|
||||
LLVMValueRef args[4] = {};
|
||||
args[0] = LLVMBuildPointerCast(p->builder, ptr, types[0], "");
|
||||
args[1] = LLVMConstInt(LLVMInt8TypeInContext(p->module->ctx), 0, false);
|
||||
args[2] = LLVMBuildIntCast2(p->builder, len, types[1], /*signed*/false, "");
|
||||
args[3] = LLVMConstInt(LLVMInt1TypeInContext(p->module->ctx), is_volatile, false);
|
||||
|
||||
return lb_call_intrinsic(p, name, args, gb_count_of(args), types, gb_count_of(types));
|
||||
} else {
|
||||
lbValue pr = lb_lookup_runtime_procedure(p->module, str_lit("memset"));
|
||||
|
||||
LLVMValueRef args[3] = {};
|
||||
args[0] = LLVMBuildPointerCast(p->builder, ptr, types[0], "");
|
||||
args[1] = LLVMConstInt(LLVMInt32TypeInContext(p->module->ctx), 0, false);
|
||||
args[2] = LLVMBuildIntCast2(p->builder, len, types[1], /*signed*/false, "");
|
||||
|
||||
// We always get the function pointer type rather than the function and there is apparently no way around that?
|
||||
LLVMTypeRef type = lb_type_internal_for_procedures_raw(p->module, pr.type);
|
||||
return LLVMBuildCall2(p->builder, type, pr.value, args, gb_count_of(args), "");
|
||||
}
|
||||
return lb_call_intrinsic(p, name, args, gb_count_of(args), types, gb_count_of(types));
|
||||
|
||||
}
|
||||
|
||||
|
||||
+21
-1
@@ -273,6 +273,7 @@ enum BuildFlagKind {
|
||||
|
||||
BuildFlag_DisallowDo,
|
||||
BuildFlag_DefaultToNilAllocator,
|
||||
BuildFlag_DefaultToPanicAllocator,
|
||||
BuildFlag_StrictStyle,
|
||||
BuildFlag_ForeignErrorProcedures,
|
||||
BuildFlag_NoRTTI,
|
||||
@@ -460,6 +461,7 @@ gb_internal bool parse_build_flags(Array<String> args) {
|
||||
|
||||
add_flag(&build_flags, BuildFlag_DisallowDo, str_lit("disallow-do"), BuildFlagParam_None, Command__does_check);
|
||||
add_flag(&build_flags, BuildFlag_DefaultToNilAllocator, str_lit("default-to-nil-allocator"), BuildFlagParam_None, Command__does_check);
|
||||
add_flag(&build_flags, BuildFlag_DefaultToPanicAllocator, str_lit("default-to-panic-allocator"),BuildFlagParam_None, Command__does_check);
|
||||
add_flag(&build_flags, BuildFlag_StrictStyle, str_lit("strict-style"), BuildFlagParam_None, Command__does_check);
|
||||
add_flag(&build_flags, BuildFlag_ForeignErrorProcedures, str_lit("foreign-error-procedures"), BuildFlagParam_None, Command__does_check);
|
||||
|
||||
@@ -471,7 +473,7 @@ gb_internal bool parse_build_flags(Array<String> args) {
|
||||
add_flag(&build_flags, BuildFlag_ObfuscateSourceCodeLocations, str_lit("obfuscate-source-code-locations"), BuildFlagParam_None, Command__does_build);
|
||||
|
||||
add_flag(&build_flags, BuildFlag_Short, str_lit("short"), BuildFlagParam_None, Command_doc);
|
||||
add_flag(&build_flags, BuildFlag_AllPackages, str_lit("all-packages"), BuildFlagParam_None, Command_doc);
|
||||
add_flag(&build_flags, BuildFlag_AllPackages, str_lit("all-packages"), BuildFlagParam_None, Command_doc | Command_test);
|
||||
add_flag(&build_flags, BuildFlag_DocFormat, str_lit("doc-format"), BuildFlagParam_None, Command_doc);
|
||||
|
||||
add_flag(&build_flags, BuildFlag_IgnoreWarnings, str_lit("ignore-warnings"), BuildFlagParam_None, Command_all);
|
||||
@@ -1122,8 +1124,20 @@ gb_internal bool parse_build_flags(Array<String> args) {
|
||||
break;
|
||||
|
||||
case BuildFlag_DefaultToNilAllocator:
|
||||
if (build_context.ODIN_DEFAULT_TO_PANIC_ALLOCATOR) {
|
||||
gb_printf_err("'-default-to-panic-allocator' cannot be used with '-default-to-nil-allocator'\n");
|
||||
bad_flags = true;
|
||||
}
|
||||
build_context.ODIN_DEFAULT_TO_NIL_ALLOCATOR = true;
|
||||
break;
|
||||
case BuildFlag_DefaultToPanicAllocator:
|
||||
if (build_context.ODIN_DEFAULT_TO_NIL_ALLOCATOR) {
|
||||
gb_printf_err("'-default-to-nil-allocator' cannot be used with '-default-to-panic-allocator'\n");
|
||||
bad_flags = true;
|
||||
}
|
||||
build_context.ODIN_DEFAULT_TO_PANIC_ALLOCATOR = true;
|
||||
break;
|
||||
|
||||
case BuildFlag_ForeignErrorProcedures:
|
||||
build_context.ODIN_FOREIGN_ERROR_PROCEDURES = true;
|
||||
break;
|
||||
@@ -1135,6 +1149,7 @@ gb_internal bool parse_build_flags(Array<String> args) {
|
||||
break;
|
||||
case BuildFlag_AllPackages:
|
||||
build_context.cmd_doc_flags |= CmdDocFlag_AllPackages;
|
||||
build_context.test_all_packages = true;
|
||||
break;
|
||||
case BuildFlag_DocFormat:
|
||||
build_context.cmd_doc_flags |= CmdDocFlag_DocFormat;
|
||||
@@ -1894,6 +1909,10 @@ gb_internal void print_show_help(String const arg0, String const &command) {
|
||||
print_usage_line(1, "-test-name:<string>");
|
||||
print_usage_line(2, "Runs specific test only by name.");
|
||||
print_usage_line(0, "");
|
||||
|
||||
print_usage_line(1, "-all-packages");
|
||||
print_usage_line(2, "Tests all packages imported into the given initial package.");
|
||||
print_usage_line(0, "");
|
||||
}
|
||||
|
||||
if (run_or_build) {
|
||||
@@ -2376,6 +2395,7 @@ int main(int arg_count, char const **arg_ptr) {
|
||||
TIME_SECTION("init default library collections");
|
||||
array_init(&library_collections, heap_allocator());
|
||||
// NOTE(bill): 'core' cannot be (re)defined by the user
|
||||
add_library_collection(str_lit("base"), get_fullpath_relative(heap_allocator(), odin_root_dir(), str_lit("base")));
|
||||
add_library_collection(str_lit("core"), get_fullpath_relative(heap_allocator(), odin_root_dir(), str_lit("core")));
|
||||
add_library_collection(str_lit("vendor"), get_fullpath_relative(heap_allocator(), odin_root_dir(), str_lit("vendor")));
|
||||
|
||||
|
||||
+29
-10
@@ -387,10 +387,11 @@ gb_internal Ast *clone_ast(Ast *node, AstFile *f) {
|
||||
n->DynamicArrayType.elem = clone_ast(n->DynamicArrayType.elem, f);
|
||||
break;
|
||||
case Ast_StructType:
|
||||
n->StructType.fields = clone_ast_array(n->StructType.fields, f);
|
||||
n->StructType.fields = clone_ast_array(n->StructType.fields, f);
|
||||
n->StructType.polymorphic_params = clone_ast(n->StructType.polymorphic_params, f);
|
||||
n->StructType.align = clone_ast(n->StructType.align, f);
|
||||
n->StructType.where_clauses = clone_ast_array(n->StructType.where_clauses, f);
|
||||
n->StructType.align = clone_ast(n->StructType.align, f);
|
||||
n->StructType.field_align = clone_ast(n->StructType.field_align, f);
|
||||
n->StructType.where_clauses = clone_ast_array(n->StructType.where_clauses, f);
|
||||
break;
|
||||
case Ast_UnionType:
|
||||
n->UnionType.variants = clone_ast_array(n->UnionType.variants, f);
|
||||
@@ -1129,7 +1130,7 @@ gb_internal Ast *ast_dynamic_array_type(AstFile *f, Token token, Ast *elem) {
|
||||
|
||||
gb_internal Ast *ast_struct_type(AstFile *f, Token token, Slice<Ast *> fields, isize field_count,
|
||||
Ast *polymorphic_params, bool is_packed, bool is_raw_union, bool is_no_copy,
|
||||
Ast *align,
|
||||
Ast *align, Ast *field_align,
|
||||
Token where_token, Array<Ast *> const &where_clauses) {
|
||||
Ast *result = alloc_ast_node(f, Ast_StructType);
|
||||
result->StructType.token = token;
|
||||
@@ -1140,6 +1141,7 @@ gb_internal Ast *ast_struct_type(AstFile *f, Token token, Slice<Ast *> fields, i
|
||||
result->StructType.is_raw_union = is_raw_union;
|
||||
result->StructType.is_no_copy = is_no_copy;
|
||||
result->StructType.align = align;
|
||||
result->StructType.field_align = field_align;
|
||||
result->StructType.where_token = where_token;
|
||||
result->StructType.where_clauses = slice_from_array(where_clauses);
|
||||
return result;
|
||||
@@ -2511,6 +2513,7 @@ gb_internal Ast *parse_operand(AstFile *f, bool lhs) {
|
||||
bool is_raw_union = false;
|
||||
bool no_copy = false;
|
||||
Ast *align = nullptr;
|
||||
Ast *field_align = nullptr;
|
||||
|
||||
if (allow_token(f, Token_OpenParen)) {
|
||||
isize param_count = 0;
|
||||
@@ -2547,6 +2550,18 @@ gb_internal Ast *parse_operand(AstFile *f, bool lhs) {
|
||||
error_line("\tSuggestion: #align(%s)", s);
|
||||
gb_string_free(s);
|
||||
}
|
||||
} else if (tag.string == "field_align") {
|
||||
if (field_align) {
|
||||
syntax_error(tag, "Duplicate struct tag '#%.*s'", LIT(tag.string));
|
||||
}
|
||||
field_align = parse_expr(f, true);
|
||||
if (field_align && field_align->kind != Ast_ParenExpr) {
|
||||
ERROR_BLOCK();
|
||||
gbString s = expr_to_string(field_align);
|
||||
syntax_warning(tag, "#field_align requires parentheses around the expression");
|
||||
error_line("\tSuggestion: #field_align(%s)", s);
|
||||
gb_string_free(s);
|
||||
}
|
||||
} else if (tag.string == "raw_union") {
|
||||
if (is_raw_union) {
|
||||
syntax_error(tag, "Duplicate struct tag '#%.*s'", LIT(tag.string));
|
||||
@@ -2595,7 +2610,7 @@ gb_internal Ast *parse_operand(AstFile *f, bool lhs) {
|
||||
decls = fields->FieldList.list;
|
||||
}
|
||||
|
||||
return ast_struct_type(f, token, decls, name_count, polymorphic_params, is_packed, is_raw_union, no_copy, align, where_token, where_clauses);
|
||||
return ast_struct_type(f, token, decls, name_count, polymorphic_params, is_packed, is_raw_union, no_copy, align, field_align, where_token, where_clauses);
|
||||
} break;
|
||||
|
||||
case Token_union: {
|
||||
@@ -5449,6 +5464,11 @@ gb_internal bool determine_path_from_string(BlockingMutex *file_mutex, Ast *node
|
||||
|
||||
|
||||
if (collection_name.len > 0) {
|
||||
// NOTE(bill): `base:runtime` == `core:runtime`
|
||||
if (collection_name == "core" && string_starts_with(file_str, str_lit("runtime"))) {
|
||||
collection_name = str_lit("base");
|
||||
}
|
||||
|
||||
if (collection_name == "system") {
|
||||
if (node->kind != Ast_ForeignImportDecl) {
|
||||
syntax_error(node, "The library collection 'system' is restrict for 'foreign_library'");
|
||||
@@ -5478,13 +5498,12 @@ gb_internal bool determine_path_from_string(BlockingMutex *file_mutex, Ast *node
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
if (is_package_name_reserved(file_str)) {
|
||||
*path = file_str;
|
||||
if (collection_name == "core") {
|
||||
if (collection_name == "core" || collection_name == "base") {
|
||||
return true;
|
||||
} else {
|
||||
syntax_error(node, "The package '%.*s' must be imported with the core library collection: 'core:%.*s'", LIT(file_str), LIT(file_str));
|
||||
syntax_error(node, "The package '%.*s' must be imported with the 'base' library collection: 'base:%.*s'", LIT(file_str), LIT(file_str));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -6122,7 +6141,7 @@ gb_internal ParseFileError parse_packages(Parser *p, String init_filename) {
|
||||
{ // Add these packages serially and then process them parallel
|
||||
TokenPos init_pos = {};
|
||||
{
|
||||
String s = get_fullpath_core(permanent_allocator(), str_lit("runtime"));
|
||||
String s = get_fullpath_base_collection(permanent_allocator(), str_lit("runtime"));
|
||||
try_add_import_path(p, s, s, init_pos, Package_Runtime);
|
||||
}
|
||||
|
||||
@@ -6130,7 +6149,7 @@ gb_internal ParseFileError parse_packages(Parser *p, String init_filename) {
|
||||
p->init_fullpath = init_fullpath;
|
||||
|
||||
if (build_context.command_kind == Command_test) {
|
||||
String s = get_fullpath_core(permanent_allocator(), str_lit("testing"));
|
||||
String s = get_fullpath_core_collection(permanent_allocator(), str_lit("testing"));
|
||||
try_add_import_path(p, s, s, init_pos, Package_Normal);
|
||||
}
|
||||
|
||||
|
||||
@@ -713,6 +713,7 @@ AST_KIND(_TypeBegin, "", bool) \
|
||||
isize field_count; \
|
||||
Ast *polymorphic_params; \
|
||||
Ast *align; \
|
||||
Ast *field_align; \
|
||||
Token where_token; \
|
||||
Slice<Ast *> where_clauses; \
|
||||
bool is_packed; \
|
||||
|
||||
+13
-5
@@ -137,6 +137,7 @@ struct TypeStruct {
|
||||
Scope * scope;
|
||||
|
||||
i64 custom_align;
|
||||
i64 custom_field_align;
|
||||
Type * polymorphic_params; // Type_Tuple
|
||||
Type * polymorphic_parent;
|
||||
|
||||
@@ -825,11 +826,13 @@ gb_internal void type_path_pop(TypePath *tp) {
|
||||
#define FAILURE_SIZE 0
|
||||
#define FAILURE_ALIGNMENT 0
|
||||
|
||||
gb_internal bool type_ptr_set_exists(PtrSet<Type *> *s, Type *t);
|
||||
|
||||
gb_internal bool type_ptr_set_update(PtrSet<Type *> *s, Type *t) {
|
||||
if (t == nullptr) {
|
||||
return true;
|
||||
}
|
||||
if (ptr_set_exists(s, t)) {
|
||||
if (type_ptr_set_exists(s, t)) {
|
||||
return true;
|
||||
}
|
||||
ptr_set_add(s, t);
|
||||
@@ -3666,10 +3669,15 @@ gb_internal i64 type_align_of_internal(Type *t, TypePath *path) {
|
||||
return gb_clamp(next_pow2(type_size_of_internal(t, path)), 1, build_context.max_align);
|
||||
}
|
||||
|
||||
gb_internal i64 *type_set_offsets_of(Slice<Entity *> const &fields, bool is_packed, bool is_raw_union) {
|
||||
gb_internal i64 *type_set_offsets_of(Slice<Entity *> const &fields, bool is_packed, bool is_raw_union, i64 min_field_align) {
|
||||
gbAllocator a = permanent_allocator();
|
||||
auto offsets = gb_alloc_array(a, i64, fields.count);
|
||||
i64 curr_offset = 0;
|
||||
|
||||
if (min_field_align == 0) {
|
||||
min_field_align = 1;
|
||||
}
|
||||
|
||||
if (is_raw_union) {
|
||||
for_array(i, fields) {
|
||||
offsets[i] = 0;
|
||||
@@ -3690,7 +3698,7 @@ gb_internal i64 *type_set_offsets_of(Slice<Entity *> const &fields, bool is_pack
|
||||
offsets[i] = -1;
|
||||
} else {
|
||||
Type *t = fields[i]->type;
|
||||
i64 align = gb_max(type_align_of(t), 1);
|
||||
i64 align = gb_max(type_align_of(t), min_field_align);
|
||||
i64 size = gb_max(type_size_of( t), 0);
|
||||
curr_offset = align_formula(curr_offset, align);
|
||||
offsets[i] = curr_offset;
|
||||
@@ -3707,7 +3715,7 @@ gb_internal bool type_set_offsets(Type *t) {
|
||||
MUTEX_GUARD(&t->Struct.offset_mutex);
|
||||
if (!t->Struct.are_offsets_set) {
|
||||
t->Struct.are_offsets_being_processed = true;
|
||||
t->Struct.offsets = type_set_offsets_of(t->Struct.fields, t->Struct.is_packed, t->Struct.is_raw_union);
|
||||
t->Struct.offsets = type_set_offsets_of(t->Struct.fields, t->Struct.is_packed, t->Struct.is_raw_union, t->Struct.custom_field_align);
|
||||
t->Struct.are_offsets_being_processed = false;
|
||||
t->Struct.are_offsets_set = true;
|
||||
return true;
|
||||
@@ -3716,7 +3724,7 @@ gb_internal bool type_set_offsets(Type *t) {
|
||||
MUTEX_GUARD(&t->Tuple.mutex);
|
||||
if (!t->Tuple.are_offsets_set) {
|
||||
t->Tuple.are_offsets_being_processed = true;
|
||||
t->Tuple.offsets = type_set_offsets_of(t->Tuple.variables, t->Tuple.is_packed, false);
|
||||
t->Tuple.offsets = type_set_offsets_of(t->Tuple.variables, t->Tuple.is_packed, false, 1);
|
||||
t->Tuple.are_offsets_being_processed = false;
|
||||
t->Tuple.are_offsets_set = true;
|
||||
return true;
|
||||
|
||||
Reference in New Issue
Block a user