Merge tag 'dev-2024-11'

This commit is contained in:
ed
2024-11-24 18:12:19 -05:00
140 changed files with 3655 additions and 1885 deletions
+14 -3
View File
@@ -62,6 +62,7 @@ gb_internal void big_int_shl (BigInt *dst, BigInt const *x, BigInt const *y);
gb_internal void big_int_shr (BigInt *dst, BigInt const *x, BigInt const *y);
gb_internal void big_int_mul (BigInt *dst, BigInt const *x, BigInt const *y);
gb_internal void big_int_mul_u64(BigInt *dst, BigInt const *x, u64 y);
gb_internal void big_int_exp_u64(BigInt *dst, BigInt const *x, u64 y, bool *success);
gb_internal void big_int_quo_rem(BigInt const *x, BigInt const *y, BigInt *q, BigInt *r);
gb_internal void big_int_quo (BigInt *z, BigInt const *x, BigInt const *y);
@@ -250,9 +251,7 @@ gb_internal void big_int_from_string(BigInt *dst, String const &s, bool *success
exp *= 10;
exp += v;
}
for (u64 x = 0; x < exp; x++) {
big_int_mul_eq(dst, &b);
}
big_int_exp_u64(dst, &b, exp, success);
}
if (is_negative) {
@@ -328,6 +327,18 @@ gb_internal void big_int_mul_u64(BigInt *dst, BigInt const *x, u64 y) {
big_int_dealloc(&d);
}
gb_internal void big_int_exp_u64(BigInt *dst, BigInt const *x, u64 y, bool *success) {
if (y > INT_MAX) {
*success = false;
return;
}
// Note: The cutoff for square-multiply being faster than the naive
// for loop is when exp > 4, but it probably isn't worth adding
// a fast path.
mp_err err = mp_expt_n(x, int(y), dst);
*success = err == MP_OKAY;
}
gb_internal void big_int_mul(BigInt *dst, BigInt const *x, BigInt const *y) {
mp_mul(x, y, dst);
+1 -1
View File
@@ -453,7 +453,7 @@ struct BuildContext {
bool no_threaded_checker;
bool show_debug_messages;
bool copy_file_contents;
bool no_rtti;
+61 -48
View File
@@ -187,10 +187,7 @@ gb_internal bool try_copy_executable_from_cache(void) {
extern char **environ;
#endif
// returns false if different, true if it is the same
gb_internal bool try_cached_build(Checker *c, Array<String> const &args) {
TEMPORARY_ALLOCATOR_GUARD();
Array<String> cache_gather_files(Checker *c) {
Parser *p = c->parser;
auto files = array_make<String>(heap_allocator());
@@ -222,29 +219,11 @@ gb_internal bool try_cached_build(Checker *c, Array<String> const &args) {
array_sort(files, string_cmp);
u64 crc = 0;
for (String const &path : files) {
crc = crc64_with_seed(path.text, path.len, crc);
}
String base_cache_dir = build_context.build_paths[BuildPath_Output].basename;
base_cache_dir = concatenate_strings(permanent_allocator(), base_cache_dir, str_lit("/.odin-cache"));
(void)check_if_exists_directory_otherwise_create(base_cache_dir);
gbString crc_str = gb_string_make_reserve(permanent_allocator(), 16);
crc_str = gb_string_append_fmt(crc_str, "%016llx", crc);
String cache_dir = concatenate3_strings(permanent_allocator(), base_cache_dir, str_lit("/"), make_string_c(crc_str));
String files_path = concatenate3_strings(permanent_allocator(), cache_dir, str_lit("/"), str_lit("files.manifest"));
String args_path = concatenate3_strings(permanent_allocator(), cache_dir, str_lit("/"), str_lit("args.manifest"));
String env_path = concatenate3_strings(permanent_allocator(), cache_dir, str_lit("/"), str_lit("env.manifest"));
build_context.build_cache_data.cache_dir = cache_dir;
build_context.build_cache_data.files_path = files_path;
build_context.build_cache_data.args_path = args_path;
build_context.build_cache_data.env_path = env_path;
return files;
}
Array<String> cache_gather_envs() {
auto envs = array_make<String>(heap_allocator());
defer (array_free(&envs));
{
#if defined(GB_SYSTEM_WINDOWS)
wchar_t *strings = GetEnvironmentStringsW();
@@ -275,19 +254,50 @@ gb_internal bool try_cached_build(Checker *c, Array<String> const &args) {
#endif
}
array_sort(envs, string_cmp);
return envs;
}
// returns false if different, true if it is the same
gb_internal bool try_cached_build(Checker *c, Array<String> const &args) {
TEMPORARY_ALLOCATOR_GUARD();
auto files = cache_gather_files(c);
auto envs = cache_gather_envs();
defer (array_free(&envs));
u64 crc = 0;
for (String const &path : files) {
crc = crc64_with_seed(path.text, path.len, crc);
}
String base_cache_dir = build_context.build_paths[BuildPath_Output].basename;
base_cache_dir = concatenate_strings(permanent_allocator(), base_cache_dir, str_lit("/.odin-cache"));
(void)check_if_exists_directory_otherwise_create(base_cache_dir);
gbString crc_str = gb_string_make_reserve(permanent_allocator(), 16);
crc_str = gb_string_append_fmt(crc_str, "%016llx", crc);
String cache_dir = concatenate3_strings(permanent_allocator(), base_cache_dir, str_lit("/"), make_string_c(crc_str));
String files_path = concatenate3_strings(permanent_allocator(), cache_dir, str_lit("/"), str_lit("files.manifest"));
String args_path = concatenate3_strings(permanent_allocator(), cache_dir, str_lit("/"), str_lit("args.manifest"));
String env_path = concatenate3_strings(permanent_allocator(), cache_dir, str_lit("/"), str_lit("env.manifest"));
build_context.build_cache_data.cache_dir = cache_dir;
build_context.build_cache_data.files_path = files_path;
build_context.build_cache_data.args_path = args_path;
build_context.build_cache_data.env_path = env_path;
if (check_if_exists_directory_otherwise_create(cache_dir)) {
goto write_cache;
return false;
}
if (check_if_exists_file_otherwise_create(files_path)) {
goto write_cache;
return false;
}
if (check_if_exists_file_otherwise_create(args_path)) {
goto write_cache;
return false;
}
if (check_if_exists_file_otherwise_create(env_path)) {
goto write_cache;
return false;
}
{
@@ -297,7 +307,7 @@ gb_internal bool try_cached_build(Checker *c, Array<String> const &args) {
LoadedFileError file_err = load_file_32(
alloc_cstring(temporary_allocator(), files_path),
&loaded_file,
false
true
);
if (file_err > LoadedFile_Empty) {
return false;
@@ -315,7 +325,7 @@ gb_internal bool try_cached_build(Checker *c, Array<String> const &args) {
}
isize sep = string_index_byte(line, ' ');
if (sep < 0) {
goto write_cache;
return false;
}
String timestamp_str = substring(line, 0, sep);
@@ -325,21 +335,21 @@ gb_internal bool try_cached_build(Checker *c, Array<String> const &args) {
path_str = string_trim_whitespace(path_str);
if (file_count >= files.count) {
goto write_cache;
return false;
}
if (files[file_count] != path_str) {
goto write_cache;
return false;
}
u64 timestamp = exact_value_to_u64(exact_value_integer_from_string(timestamp_str));
gbFileTime last_write_time = gb_file_last_write_time(alloc_cstring(temporary_allocator(), path_str));
if (last_write_time != timestamp) {
goto write_cache;
return false;
}
}
if (file_count != files.count) {
goto write_cache;
return false;
}
}
{
@@ -348,7 +358,7 @@ gb_internal bool try_cached_build(Checker *c, Array<String> const &args) {
LoadedFileError file_err = load_file_32(
alloc_cstring(temporary_allocator(), args_path),
&loaded_file,
false
true
);
if (file_err > LoadedFile_Empty) {
return false;
@@ -366,11 +376,11 @@ gb_internal bool try_cached_build(Checker *c, Array<String> const &args) {
break;
}
if (args_count >= args.count) {
goto write_cache;
return false;
}
if (line != args[args_count]) {
goto write_cache;
return false;
}
}
}
@@ -380,7 +390,7 @@ gb_internal bool try_cached_build(Checker *c, Array<String> const &args) {
LoadedFileError file_err = load_file_32(
alloc_cstring(temporary_allocator(), env_path),
&loaded_file,
false
true
);
if (file_err > LoadedFile_Empty) {
return false;
@@ -398,20 +408,26 @@ gb_internal bool try_cached_build(Checker *c, Array<String> const &args) {
break;
}
if (env_count >= envs.count) {
goto write_cache;
return false;
}
if (line != envs[env_count]) {
goto write_cache;
return false;
}
}
}
return try_copy_executable_from_cache();
}
void write_cached_build(Checker *c, Array<String> const &args) {
auto files = cache_gather_files(c);
defer (array_free(&files));
auto envs = cache_gather_envs();
defer (array_free(&envs));
write_cache:;
{
char const *path_c = alloc_cstring(temporary_allocator(), files_path);
char const *path_c = alloc_cstring(temporary_allocator(), build_context.build_cache_data.files_path);
gb_file_remove(path_c);
debugf("Cache: updating %s\n", path_c);
@@ -426,7 +442,7 @@ write_cache:;
}
}
{
char const *path_c = alloc_cstring(temporary_allocator(), args_path);
char const *path_c = alloc_cstring(temporary_allocator(), build_context.build_cache_data.args_path);
gb_file_remove(path_c);
debugf("Cache: updating %s\n", path_c);
@@ -441,7 +457,7 @@ write_cache:;
}
}
{
char const *path_c = alloc_cstring(temporary_allocator(), env_path);
char const *path_c = alloc_cstring(temporary_allocator(), build_context.build_cache_data.env_path);
gb_file_remove(path_c);
debugf("Cache: updating %s\n", path_c);
@@ -454,8 +470,5 @@ write_cache:;
gb_fprintf(&f, "%.*s\n", LIT(env));
}
}
return false;
}
+5 -1
View File
@@ -1533,6 +1533,10 @@ gb_internal LoadDirectiveResult check_load_directory_directive(CheckerContext *c
for (FileInfo fi : list) {
LoadFileCache *cache = nullptr;
if (fi.is_dir) {
continue;
}
if (cache_load_file_directive(c, call, fi.fullpath, err_on_not_found, &cache, LoadFileTier_Contents, /*use_mutex*/false)) {
array_add(&file_caches, cache);
} else {
@@ -2074,8 +2078,8 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As
bool ok = check_builtin_simd_operation(c, operand, call, id, type_hint);
if (!ok) {
operand->type = t_invalid;
operand->mode = Addressing_Value;
}
operand->mode = Addressing_Value;
operand->value = {};
operand->expr = call;
return ok;
+4 -3
View File
@@ -88,11 +88,12 @@ gb_internal Type *check_init_variable(CheckerContext *ctx, Entity *e, Operand *o
e->type = t_invalid;
return nullptr;
} else if (is_type_polymorphic(t)) {
Entity *e = entity_of_node(operand->expr);
if (e == nullptr) {
Entity *e2 = entity_of_node(operand->expr);
if (e2 == nullptr) {
e->type = t_invalid;
return nullptr;
}
if (e->state.load() != EntityState_Resolved) {
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));
+16 -12
View File
@@ -5394,22 +5394,25 @@ gb_internal Entity *check_selector(CheckerContext *c, Operand *operand, Ast *nod
Type *t = type_deref(operand->type);
if (t == nullptr) {
error(operand->expr, "Cannot use a selector expression on 0-value expression");
} else if (is_type_dynamic_array(t)) {
init_mem_allocator(c->checker);
}
sel = lookup_field(operand->type, field_name, operand->mode == Addressing_Type);
entity = sel.entity;
} else {
if (is_type_dynamic_array(t)) {
init_mem_allocator(c->checker);
}
sel = lookup_field(operand->type, field_name, operand->mode == Addressing_Type);
entity = sel.entity;
// NOTE(bill): Add type info needed for fields like 'names'
if (entity != nullptr && (entity->flags&EntityFlag_TypeField)) {
add_type_info_type(c, operand->type);
}
if (is_type_enum(operand->type)) {
add_type_info_type(c, operand->type);
// NOTE(bill): Add type info needed for fields like 'names'
if (entity != nullptr && (entity->flags&EntityFlag_TypeField)) {
add_type_info_type(c, operand->type);
}
if (is_type_enum(operand->type)) {
add_type_info_type(c, operand->type);
}
}
}
if (entity == nullptr && selector->kind == Ast_Ident && (is_type_array(type_deref(operand->type)) || is_type_simd_vector(type_deref(operand->type)))) {
if (entity == nullptr && selector->kind == Ast_Ident && operand->type != nullptr &&
(is_type_array(type_deref(operand->type)) || is_type_simd_vector(type_deref(operand->type)))) {
String field_name = selector->Ident.token.string;
if (1 < field_name.len && field_name.len <= 4) {
u8 swizzles_xyzw[4] = {'x', 'y', 'z', 'w'};
@@ -8010,6 +8013,7 @@ gb_internal ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *c
pt = data.gen_entity->type;
}
}
pt = base_type(pt);
if (pt->kind == Type_Proc && pt->Proc.calling_convention == ProcCC_Odin) {
if ((c->scope->flags & ScopeFlag_ContextDefined) == 0) {
+17
View File
@@ -2600,6 +2600,23 @@ gb_internal void check_for_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) {
check_expr(ctx, &o, fs->cond);
if (o.mode != Addressing_Invalid && !is_type_boolean(o.type)) {
error(fs->cond, "Non-boolean condition in 'for' statement");
} else {
Ast *cond = unparen_expr(o.expr);
if (cond && cond->kind == Ast_BinaryExpr &&
cond->BinaryExpr.left && cond->BinaryExpr.right &&
cond->BinaryExpr.op.kind == Token_GtEq &&
is_type_unsigned(type_of_expr(cond->BinaryExpr.left)) &&
cond->BinaryExpr.right->tav.value.kind == ExactValue_Integer &&
is_exact_value_zero(cond->BinaryExpr.right->tav.value)) {
warning(cond, "Expression is always true since unsigned numbers are always >= 0");
} else if (cond && cond->kind == Ast_BinaryExpr &&
cond->BinaryExpr.left && cond->BinaryExpr.right &&
cond->BinaryExpr.op.kind == Token_LtEq &&
is_type_unsigned(type_of_expr(cond->BinaryExpr.right)) &&
cond->BinaryExpr.left->tav.value.kind == ExactValue_Integer &&
is_exact_value_zero(cond->BinaryExpr.left->tav.value)) {
warning(cond, "Expression is always true since unsigned numbers are always >= 0");
}
}
}
if (fs->post != nullptr) {
+1
View File
@@ -687,6 +687,7 @@ gb_internal void match_exact_values(ExactValue *x, ExactValue *y) {
case ExactValue_String:
case ExactValue_Quaternion:
case ExactValue_Pointer:
case ExactValue_Compound:
case ExactValue_Procedure:
case ExactValue_Typeid:
return;
+5 -1
View File
@@ -2541,7 +2541,11 @@ gb_inline void const *gb_pointer_add_const(void const *ptr, isize bytes) {
gb_inline void const *gb_pointer_sub_const(void const *ptr, isize bytes) { return cast(void const *)(cast(u8 const *)ptr - bytes); }
gb_inline isize gb_pointer_diff (void const *begin, void const *end) { return cast(isize)(cast(u8 const *)end - cast(u8 const *)begin); }
gb_inline void gb_zero_size(void *ptr, isize size) { memset(ptr, 0, size); }
gb_inline void gb_zero_size(void *ptr, isize size) {
if (size != 0) {
memset(ptr, 0, size);
}
}
#if defined(_MSC_VER) && !defined(__clang__)
+13 -4
View File
@@ -605,9 +605,18 @@ gb_internal i32 linker_stage(LinkerData *gen) {
link_settings = gb_string_appendc(link_settings, "-Wl,-fini,'_odin_exit_point' ");
}
} else if (build_context.metrics.os != TargetOs_openbsd && build_context.metrics.os != TargetOs_haiku && build_context.metrics.arch != TargetArch_riscv64) {
// OpenBSD and Haiku default to PIE executable. do not pass -no-pie for it.
link_settings = gb_string_appendc(link_settings, "-no-pie ");
}
if (build_context.build_mode == BuildMode_Executable && build_context.reloc_mode == RelocMode_PIC) {
// Do not disable PIE, let the linker choose. (most likely you want it enabled)
} else if (build_context.build_mode != BuildMode_DynamicLibrary) {
if (build_context.metrics.os != TargetOs_openbsd
&& build_context.metrics.os != TargetOs_haiku
&& build_context.metrics.arch != TargetArch_riscv64
) {
// OpenBSD and Haiku default to PIE executable. do not pass -no-pie for it.
link_settings = gb_string_appendc(link_settings, "-no-pie ");
}
}
gbString platform_lib_str = gb_string_make(heap_allocator(), "");
@@ -684,7 +693,7 @@ gb_internal i32 linker_stage(LinkerData *gen) {
if (is_osx && build_context.ODIN_DEBUG) {
// NOTE: macOS links DWARF symbols dynamically. Dsymutil will map the stubs in the exe
// to the symbols in the object file
result = system_exec_command_line_app("dsymutil", "dsymutil %.*s", LIT(output_filename));
result = system_exec_command_line_app("dsymutil", "dsymutil \"%.*s\"", LIT(output_filename));
if (result) {
return result;
+19 -9
View File
@@ -130,7 +130,7 @@ gb_internal lbValue lb_emit_unary_arith(lbProcedure *p, TokenKind op, lbValue x,
LLVMTypeRef vector_type = nullptr;
if (op != Token_Not && lb_try_vector_cast(p->module, val, &vector_type)) {
LLVMValueRef vp = LLVMBuildPointerCast(p->builder, val.value, LLVMPointerType(vector_type, 0), "");
LLVMValueRef v = LLVMBuildLoad2(p->builder, vector_type, vp, "");
LLVMValueRef v = OdinLLVMBuildLoad(p, vector_type, vp);
LLVMValueRef opv = nullptr;
switch (op) {
@@ -324,8 +324,8 @@ gb_internal bool lb_try_direct_vector_arith(lbProcedure *p, TokenKind op, lbValu
LLVMValueRef lhs_vp = LLVMBuildPointerCast(p->builder, lhs_ptr.value, LLVMPointerType(vector_type, 0), "");
LLVMValueRef rhs_vp = LLVMBuildPointerCast(p->builder, rhs_ptr.value, LLVMPointerType(vector_type, 0), "");
LLVMValueRef x = LLVMBuildLoad2(p->builder, vector_type, lhs_vp, "");
LLVMValueRef y = LLVMBuildLoad2(p->builder, vector_type, rhs_vp, "");
LLVMValueRef x = OdinLLVMBuildLoad(p, vector_type, lhs_vp);
LLVMValueRef y = OdinLLVMBuildLoad(p, vector_type, rhs_vp);
LLVMValueRef z = nullptr;
if (is_type_float(integral_type)) {
@@ -551,15 +551,14 @@ gb_internal LLVMValueRef lb_matrix_to_vector(lbProcedure *p, lbValue matrix) {
Type *mt = base_type(matrix.type);
GB_ASSERT(mt->kind == Type_Matrix);
LLVMTypeRef elem_type = lb_type(p->module, mt->Matrix.elem);
unsigned total_count = cast(unsigned)matrix_type_total_internal_elems(mt);
LLVMTypeRef total_matrix_type = LLVMVectorType(elem_type, total_count);
#if 1
LLVMValueRef ptr = lb_address_from_load_or_generate_local(p, matrix).value;
LLVMValueRef matrix_vector_ptr = LLVMBuildPointerCast(p->builder, ptr, LLVMPointerType(total_matrix_type, 0), "");
LLVMValueRef matrix_vector = LLVMBuildLoad2(p->builder, total_matrix_type, matrix_vector_ptr, "");
LLVMSetAlignment(matrix_vector, cast(unsigned)type_align_of(mt));
LLVMValueRef matrix_vector = OdinLLVMBuildLoadAligned(p, total_matrix_type, matrix_vector_ptr, type_align_of(mt));
return matrix_vector;
#else
LLVMValueRef matrix_vector = LLVMBuildBitCast(p->builder, matrix.value, total_matrix_type, "");
@@ -1648,7 +1647,7 @@ gb_internal lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) {
lb_emit_store(p, a1, id);
return lb_addr_load(p, res);
} else if (dst->kind == Type_Basic) {
if (src->Basic.kind == Basic_string && dst->Basic.kind == Basic_cstring) {
if (src->kind == Type_Basic && src->Basic.kind == Basic_string && dst->Basic.kind == Basic_cstring) {
String str = lb_get_const_string(m, value);
lbValue res = {};
res.type = t;
@@ -2364,12 +2363,23 @@ gb_internal lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) {
GB_ASSERT(src->kind == Type_Matrix);
lbAddr v = lb_add_local_generated(p, t, true);
if (is_matrix_square(dst) && is_matrix_square(dst)) {
if (dst->Matrix.row_count == src->Matrix.row_count &&
dst->Matrix.column_count == src->Matrix.column_count) {
for (i64 j = 0; j < dst->Matrix.column_count; j++) {
for (i64 i = 0; i < dst->Matrix.row_count; i++) {
lbValue d = lb_emit_matrix_epi(p, v.addr, i, j);
lbValue s = lb_emit_matrix_ev(p, value, i, j);
s = lb_emit_conv(p, s, dst->Matrix.elem);
lb_emit_store(p, d, s);
}
}
} else if (is_matrix_square(dst) && is_matrix_square(dst)) {
for (i64 j = 0; j < dst->Matrix.column_count; j++) {
for (i64 i = 0; i < dst->Matrix.row_count; i++) {
if (i < src->Matrix.row_count && j < src->Matrix.column_count) {
lbValue d = lb_emit_matrix_epi(p, v.addr, i, j);
lbValue s = lb_emit_matrix_ev(p, value, i, j);
s = lb_emit_conv(p, s, dst->Matrix.elem);
lb_emit_store(p, d, s);
} else if (i == j) {
lbValue d = lb_emit_matrix_epi(p, v.addr, i, j);
+40 -19
View File
@@ -722,7 +722,10 @@ gb_internal unsigned lb_try_get_alignment(LLVMValueRef addr_ptr, unsigned defaul
gb_internal bool lb_try_update_alignment(LLVMValueRef addr_ptr, unsigned alignment) {
if (LLVMIsAGlobalValue(addr_ptr) || LLVMIsAAllocaInst(addr_ptr) || LLVMIsALoadInst(addr_ptr)) {
if (LLVMGetAlignment(addr_ptr) < alignment) {
if (LLVMIsAAllocaInst(addr_ptr) || LLVMIsAGlobalValue(addr_ptr)) {
if (LLVMIsAAllocaInst(addr_ptr)) {
LLVMSetAlignment(addr_ptr, alignment);
} else if (LLVMIsAGlobalValue(addr_ptr) && LLVMGetLinkage(addr_ptr) != LLVMExternalLinkage) {
// NOTE(laytan): setting alignment of an external global just changes the alignment we expect it to be.
LLVMSetAlignment(addr_ptr, alignment);
}
}
@@ -755,10 +758,7 @@ gb_internal bool lb_try_vector_cast(lbModule *m, lbValue ptr, LLVMTypeRef *vecto
LLVMValueRef addr_ptr = ptr.value;
if (LLVMIsAAllocaInst(addr_ptr) || LLVMIsAGlobalValue(addr_ptr)) {
unsigned alignment = LLVMGetAlignment(addr_ptr);
alignment = gb_max(alignment, vector_alignment);
possible = true;
LLVMSetAlignment(addr_ptr, alignment);
possible = lb_try_update_alignment(addr_ptr, vector_alignment);
} else if (LLVMIsALoadInst(addr_ptr)) {
unsigned alignment = LLVMGetAlignment(addr_ptr);
possible = alignment >= vector_alignment;
@@ -774,6 +774,36 @@ gb_internal bool lb_try_vector_cast(lbModule *m, lbValue ptr, LLVMTypeRef *vecto
return false;
}
gb_internal LLVMValueRef OdinLLVMBuildLoad(lbProcedure *p, LLVMTypeRef type, LLVMValueRef value) {
LLVMValueRef result = LLVMBuildLoad2(p->builder, type, value, "");
// If it is not an instruction it isn't a GEP, so we don't need to track alignment in the metadata,
// which is not possible anyway (only LLVM instructions can have metadata).
if (LLVMIsAInstruction(value)) {
u64 is_packed = lb_get_metadata_custom_u64(p->module, value, ODIN_METADATA_IS_PACKED);
if (is_packed != 0) {
LLVMSetAlignment(result, 1);
}
}
return result;
}
gb_internal LLVMValueRef OdinLLVMBuildLoadAligned(lbProcedure *p, LLVMTypeRef type, LLVMValueRef value, i64 alignment) {
LLVMValueRef result = LLVMBuildLoad2(p->builder, type, value, "");
LLVMSetAlignment(result, cast(unsigned)alignment);
if (LLVMIsAInstruction(value)) {
u64 is_packed = lb_get_metadata_custom_u64(p->module, value, ODIN_METADATA_IS_PACKED);
if (is_packed != 0) {
LLVMSetAlignment(result, 1);
}
}
return result;
}
gb_internal void lb_addr_store(lbProcedure *p, lbAddr addr, lbValue value) {
if (addr.addr.value == nullptr) {
return;
@@ -1119,7 +1149,7 @@ gb_internal lbValue lb_emit_load(lbProcedure *p, lbValue value) {
Type *vt = base_type(value.type);
GB_ASSERT(vt->kind == Type_MultiPointer);
Type *t = vt->MultiPointer.elem;
LLVMValueRef v = LLVMBuildLoad2(p->builder, lb_type(p->module, t), value.value, "");
LLVMValueRef v = OdinLLVMBuildLoad(p, lb_type(p->module, t), value.value);
return lbValue{v, t};
} else if (is_type_soa_pointer(value.type)) {
lbValue ptr = lb_emit_struct_ev(p, value, 0);
@@ -1130,16 +1160,7 @@ gb_internal lbValue lb_emit_load(lbProcedure *p, lbValue value) {
GB_ASSERT_MSG(is_type_pointer(value.type), "%s", type_to_string(value.type));
Type *t = type_deref(value.type);
LLVMValueRef v = LLVMBuildLoad2(p->builder, lb_type(p->module, t), value.value, "");
// If it is not an instruction it isn't a GEP, so we don't need to track alignment in the metadata,
// which is not possible anyway (only LLVM instructions can have metadata).
if (LLVMIsAInstruction(value.value)) {
u64 is_packed = lb_get_metadata_custom_u64(p->module, value.value, ODIN_METADATA_IS_PACKED);
if (is_packed != 0) {
LLVMSetAlignment(v, 1);
}
}
LLVMValueRef v = OdinLLVMBuildLoad(p, lb_type(p->module, t), value.value);
return lbValue{v, t};
}
@@ -1413,7 +1434,7 @@ gb_internal lbValue lb_addr_load(lbProcedure *p, lbAddr const &addr) {
LLVMTypeRef vector_type = nullptr;
if (lb_try_vector_cast(p->module, addr.addr, &vector_type)) {
LLVMValueRef vp = LLVMBuildPointerCast(p->builder, addr.addr.value, LLVMPointerType(vector_type, 0), "");
LLVMValueRef v = LLVMBuildLoad2(p->builder, vector_type, vp, "");
LLVMValueRef v = OdinLLVMBuildLoad(p, vector_type, vp);
LLVMValueRef scalars[4] = {};
for (u8 i = 0; i < addr.swizzle.count; i++) {
scalars[i] = LLVMConstInt(lb_type(p->module, t_u32), addr.swizzle.indices[i], false);
@@ -2710,7 +2731,7 @@ general_end:;
if (LLVMIsALoadInst(val) && (src_size >= dst_size && src_align >= dst_align)) {
LLVMValueRef val_ptr = LLVMGetOperand(val, 0);
val_ptr = LLVMBuildPointerCast(p->builder, val_ptr, LLVMPointerType(dst_type, 0), "");
LLVMValueRef loaded_val = LLVMBuildLoad2(p->builder, dst_type, val_ptr, "");
LLVMValueRef loaded_val = OdinLLVMBuildLoad(p, dst_type, val_ptr);
// LLVMSetAlignment(loaded_val, gb_min(src_align, dst_align));
@@ -2726,7 +2747,7 @@ general_end:;
LLVMValueRef nptr = LLVMBuildPointerCast(p->builder, ptr, LLVMPointerType(src_type, 0), "");
LLVMBuildStore(p->builder, val, nptr);
return LLVMBuildLoad2(p->builder, dst_type, ptr, "");
return OdinLLVMBuildLoad(p, dst_type, ptr);
}
}
+2 -3
View File
@@ -2568,7 +2568,7 @@ gb_internal lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValu
case BuiltinProc_atomic_load_explicit: {
lbValue dst = lb_build_expr(p, ce->args[0]);
LLVMValueRef instr = LLVMBuildLoad2(p->builder, lb_type(p->module, type_deref(dst.type)), dst.value, "");
LLVMValueRef instr = OdinLLVMBuildLoad(p, lb_type(p->module, type_deref(dst.type)), dst.value);
switch (id) {
case BuiltinProc_non_temporal_load:
{
@@ -2621,8 +2621,7 @@ gb_internal lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValu
if (is_type_simd_vector(t)) {
lbValue res = {};
res.type = t;
res.value = LLVMBuildLoad2(p->builder, lb_type(p->module, t), src.value, "");
LLVMSetAlignment(res.value, 1);
res.value = OdinLLVMBuildLoadAligned(p, lb_type(p->module, t), src.value, 1);
return res;
} else {
lbAddr dst = lb_add_local_generated(p, t, false);
+12 -9
View File
@@ -2001,7 +2001,7 @@ gb_internal void lb_build_return_stmt_internal(lbProcedure *p, lbValue res) {
LLVMValueRef ptr = p->temp_callee_return_struct_memory;
LLVMValueRef nptr = LLVMBuildPointerCast(p->builder, ptr, LLVMPointerType(src_type, 0), "");
LLVMBuildStore(p->builder, ret_val, nptr);
ret_val = LLVMBuildLoad2(p->builder, ret_type, ptr, "");
ret_val = OdinLLVMBuildLoad(p, ret_type, ptr);
} else {
ret_val = OdinLLVMBuildTransmute(p, ret_val, ret_type);
}
@@ -2018,14 +2018,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) {
lb_ensure_abi_function_type(p->module, p);
lbValue res = {};
TypeTuple *tuple = &p->type->Proc.results->Tuple;
isize return_count = p->type->Proc.result_count;
isize res_count = return_results.count;
lbFunctionType *ft = lb_get_function_type(p->module, p->type);
bool return_by_pointer = ft->ret.kind == lbArg_Indirect;
if (return_count == 0) {
// No return values
@@ -2038,7 +2031,17 @@ gb_internal void lb_build_return_stmt(lbProcedure *p, Slice<Ast *> const &return
LLVMBuildRetVoid(p->builder);
}
return;
} else if (return_count == 1) {
}
lbValue res = {};
TypeTuple *tuple = &p->type->Proc.results->Tuple;
isize res_count = return_results.count;
lbFunctionType *ft = lb_get_function_type(p->module, p->type);
bool return_by_pointer = ft->ret.kind == lbArg_Indirect;
if (return_count == 1) {
Entity *e = tuple->variables[0];
if (res_count == 0) {
rw_mutex_shared_lock(&p->module->values_mutex);
+2
View File
@@ -43,6 +43,8 @@ gb_internal u64 lb_typeid_kind(lbModule *m, Type *type, u64 id=0) {
if (flags & BasicFlag_Pointer) kind = Typeid_Pointer;
if (flags & BasicFlag_String) kind = Typeid_String;
if (flags & BasicFlag_Rune) kind = Typeid_Rune;
if (bt->Basic.kind == Basic_typeid) kind = Typeid_Type_Id;
} break;
case Type_Pointer: kind = Typeid_Pointer; break;
case Type_MultiPointer: kind = Typeid_Multi_Pointer; break;
+1 -1
View File
@@ -269,7 +269,7 @@ gb_internal lbValue lb_emit_transmute(lbProcedure *p, lbValue value, Type *t) {
if (lb_try_update_alignment(ptr, align)) {
LLVMTypeRef result_type = lb_type(p->module, t);
res.value = LLVMBuildPointerCast(p->builder, ptr.value, LLVMPointerType(result_type, 0), "");
res.value = LLVMBuildLoad2(p->builder, result_type, res.value, "");
res.value = OdinLLVMBuildLoad(p, result_type, res.value);
return res;
}
lbAddr addr = lb_add_local_generated(p, t, false);
+15 -7
View File
@@ -2199,6 +2199,7 @@ gb_internal void print_show_help(String const arg0, String const &command) {
print_usage_line(3, "-build-mode:test Builds as an executable that executes tests.");
print_usage_line(3, "-build-mode:dll Builds as a dynamically linked library.");
print_usage_line(3, "-build-mode:shared Builds as a dynamically linked library.");
print_usage_line(3, "-build-mode:dynamic Builds as a dynamically linked library.");
print_usage_line(3, "-build-mode:lib Builds as a statically linked library.");
print_usage_line(3, "-build-mode:static Builds as a statically linked library.");
print_usage_line(3, "-build-mode:obj Builds as an object file.");
@@ -3391,6 +3392,7 @@ int main(int arg_count, char const **arg_ptr) {
Parser *parser = gb_alloc_item(permanent_allocator(), Parser);
Checker *checker = gb_alloc_item(permanent_allocator(), Checker);
bool failed_to_cache_parsing = false;
MAIN_TIME_SECTION("parse files");
@@ -3480,6 +3482,7 @@ int main(int arg_count, char const **arg_ptr) {
if (try_cached_build(checker, args)) {
goto end_of_code_gen;
}
failed_to_cache_parsing = true;
}
#if ALLOW_TILDE
@@ -3545,18 +3548,23 @@ int main(int arg_count, char const **arg_ptr) {
end_of_code_gen:;
if (build_context.show_timings) {
show_timings(checker, &global_timings);
}
if (build_context.export_dependencies_format != DependenciesExportUnspecified) {
export_dependencies(checker);
}
if (build_context.cached) {
MAIN_TIME_SECTION("write cached build");
if (!build_context.build_cache_data.copy_already_done) {
try_copy_executable_to_cache();
}
if (!build_context.build_cache_data.copy_already_done &&
build_context.cached) {
try_copy_executable_to_cache();
if (failed_to_cache_parsing) {
write_cached_build(checker, args);
}
}
if (build_context.show_timings) {
show_timings(checker, &global_timings);
}
if (run_output) {
-2
View File
@@ -4262,8 +4262,6 @@ gb_internal bool allow_field_separator(AstFile *f) {
gb_internal Ast *parse_struct_field_list(AstFile *f, isize *name_count_) {
Token start_token = f->curr_token;
auto decls = array_make<Ast *>(ast_allocator(f));
isize total_name_count = 0;
Ast *params = parse_field_list(f, &total_name_count, FieldFlag_Struct, Token_CloseBrace, false, false);
+1
View File
@@ -156,6 +156,7 @@ gb_internal isize string_index_byte(String const &s, u8 x) {
gb_internal gb_inline bool str_eq(String const &a, String const &b) {
if (a.len != b.len) return false;
if (a.len == 0) return true;
return memcmp(a.text, b.text, a.len) == 0;
}
gb_internal gb_inline bool str_ne(String const &a, String const &b) { return !str_eq(a, b); }
+9 -4
View File
@@ -1,10 +1,15 @@
#pragma warning(push)
#pragma warning(disable: 4245)
#if defined(GB_SYSTEM_WINDOWS)
#pragma warning(push)
#pragma warning(disable: 4245)
#endif
extern "C" {
#include "utf8proc/utf8proc.c"
}
#pragma warning(pop)
#if defined(GB_SYSTEM_WINDOWS)
#pragma warning(pop)
#endif
gb_internal bool rune_is_letter(Rune r) {
@@ -109,7 +114,7 @@ gb_internal isize utf8_decode(u8 const *str, isize str_len, Rune *codepoint_out)
u8 b1, b2, b3;
Utf8AcceptRange accept;
if (x >= 0xf0) {
Rune mask = (cast(Rune)x << 31) >> 31;
Rune mask = -cast(Rune)(x & 1);
codepoint = (cast(Rune)s0 & (~mask)) | (GB_RUNE_INVALID & mask);
width = 1;
goto end;