Merge remote-tracking branch 'upstream/master'

This commit is contained in:
FourteenBrush
2024-02-02 21:01:52 +01:00
265 changed files with 2038 additions and 1580 deletions
+35 -3
View File
@@ -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;
}
+2
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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) {
+10 -10
View File
@@ -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
+5
View File
@@ -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");
+3 -3
View File
@@ -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:
+6 -20
View File
@@ -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
View File
@@ -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
View File
@@ -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);
}
+1
View File
@@ -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
View File
@@ -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;