aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/build_settings.cpp8
-rw-r--r--src/check_builtin.cpp10
-rw-r--r--src/check_expr.cpp2
-rw-r--r--src/llvm_backend.cpp7
-rw-r--r--src/llvm_backend_debug.cpp55
-rw-r--r--src/llvm_backend_expr.cpp56
-rw-r--r--src/main.cpp5
-rw-r--r--src/types.cpp20
8 files changed, 119 insertions, 44 deletions
diff --git a/src/build_settings.cpp b/src/build_settings.cpp
index fe0e478c7..e86224665 100644
--- a/src/build_settings.cpp
+++ b/src/build_settings.cpp
@@ -430,6 +430,7 @@ struct BuildContext {
bool json_errors;
bool has_ansi_terminal_colours;
+ bool fast_isel;
bool ignore_lazy;
bool ignore_llvm_build;
bool ignore_panic;
@@ -2048,10 +2049,11 @@ gb_internal bool init_build_paths(String init_filename) {
gbFile output_file_test;
const char* output_file_name = (const char*)output_file.text;
gbFileError output_test_err = gb_file_open_mode(&output_file_test, gbFileMode_Append | gbFileMode_Rw, output_file_name);
- gb_file_close(&output_file_test);
- gb_file_remove(output_file_name);
- if (output_test_err != 0) {
+ if (output_test_err == 0) {
+ gb_file_close(&output_file_test);
+ gb_file_remove(output_file_name);
+ } else {
String output_file = path_to_string(ha, bc->build_paths[BuildPath_Output]);
defer (gb_free(ha, output_file.text));
gb_printf_err("No write permissions for output path: %.*s\n", LIT(output_file));
diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp
index 910e7ffdb..888aa074d 100644
--- a/src/check_builtin.cpp
+++ b/src/check_builtin.cpp
@@ -5203,6 +5203,16 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As
return false;
}
+ if (sz >= 64) {
+ if (is_type_unsigned(x.type)) {
+ add_package_dependency(c, "runtime", "umodti3", true);
+ add_package_dependency(c, "runtime", "udivti3", true);
+ } else {
+ add_package_dependency(c, "runtime", "modti3", true);
+ add_package_dependency(c, "runtime", "divti3", true);
+ }
+ }
+
operand->type = x.type;
operand->mode = Addressing_Value;
}
diff --git a/src/check_expr.cpp b/src/check_expr.cpp
index 6ab87da09..27ba2448e 100644
--- a/src/check_expr.cpp
+++ b/src/check_expr.cpp
@@ -3615,7 +3615,7 @@ gb_internal bool check_transmute(CheckerContext *c, Ast *node, Operand *o, Type
if (is_type_integer(src_t) && is_type_integer(dst_t)) {
if (types_have_same_internal_endian(src_t, dst_t)) {
ExactValue src_v = exact_value_to_integer(o->value);
- GB_ASSERT(src_v.kind == ExactValue_Integer);
+ GB_ASSERT(src_v.kind == ExactValue_Integer || src_v.kind == ExactValue_Invalid);
BigInt v = src_v.value_integer;
BigInt smax = {};
diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp
index f852636a6..01ded321e 100644
--- a/src/llvm_backend.cpp
+++ b/src/llvm_backend.cpp
@@ -3081,6 +3081,13 @@ gb_internal bool lb_generate_code(lbGenerator *gen) {
lbModule *m = entry.value;
m->target_machine = target_machine;
LLVMSetModuleDataLayout(m->mod, LLVMCreateTargetDataLayout(target_machine));
+
+ #if LLVM_VERSION_MAJOR >= 18
+ if (build_context.fast_isel) {
+ LLVMSetTargetMachineFastISel(m->target_machine, true);
+ }
+ #endif
+
array_add(&target_machines, target_machine);
}
diff --git a/src/llvm_backend_debug.cpp b/src/llvm_backend_debug.cpp
index 5d90dccea..68e1efc1c 100644
--- a/src/llvm_backend_debug.cpp
+++ b/src/llvm_backend_debug.cpp
@@ -82,13 +82,36 @@ gb_internal LLVMMetadataRef lb_debug_type_internal_proc(lbModule *m, Type *type)
parameter_count += 1;
}
}
- LLVMMetadataRef *parameters = gb_alloc_array(permanent_allocator(), LLVMMetadataRef, parameter_count);
- unsigned param_index = 0;
- if (type->Proc.result_count == 0) {
- parameters[param_index++] = nullptr;
- } else {
- parameters[param_index++] = lb_debug_procedure_parameters(m, type->Proc.results);
+ auto parameters = array_make<LLVMMetadataRef>(permanent_allocator(), 0, type->Proc.param_count+type->Proc.result_count+2);
+
+ array_add(&parameters, cast(LLVMMetadataRef)nullptr);
+
+ bool return_is_tuple = false;
+ if (type->Proc.result_count != 0) {
+ Type *single_ret = reduce_tuple_to_single_type(type->Proc.results);
+ if (is_type_proc(single_ret)) {
+ single_ret = t_rawptr;
+ }
+ if (is_type_tuple(single_ret) && is_calling_convention_odin(type->Proc.calling_convention)) {
+ LLVMTypeRef actual = lb_type_internal_for_procedures_raw(m, type);
+ actual = LLVMGetReturnType(actual);
+ if (actual == nullptr) {
+ // results were passed as a single pointer
+ parameters[0] = lb_debug_procedure_parameters(m, single_ret);
+ } else {
+ LLVMTypeRef possible = lb_type(m, type->Proc.results);
+ if (possible == actual) {
+ // results were returned directly
+ parameters[0] = lb_debug_procedure_parameters(m, single_ret);
+ } else {
+ // resulsts were returned separately
+ return_is_tuple = true;
+ }
+ }
+ } else {
+ parameters[0] = lb_debug_procedure_parameters(m, single_ret);
+ }
}
LLVMMetadataRef file = nullptr;
@@ -98,8 +121,22 @@ gb_internal LLVMMetadataRef lb_debug_type_internal_proc(lbModule *m, Type *type)
if (e->kind != Entity_Variable) {
continue;
}
- parameters[param_index] = lb_debug_procedure_parameters(m, e->type);
- param_index += 1;
+ array_add(&parameters, lb_debug_procedure_parameters(m, e->type));
+ }
+
+
+ if (return_is_tuple) {
+ Type *results = type->Proc.results;
+ GB_ASSERT(results != nullptr && results->kind == Type_Tuple);
+ isize count = results->Tuple.variables.count;
+ parameters[0] = lb_debug_procedure_parameters(m, results->Tuple.variables[count-1]->type);
+ for (isize i = 0; i < count-1; i++) {
+ array_add(&parameters, lb_debug_procedure_parameters(m, results->Tuple.variables[i]->type));
+ }
+ }
+
+ if (type->Proc.calling_convention == ProcCC_Odin) {
+ array_add(&parameters, lb_debug_type(m, t_context_ptr));
}
LLVMDIFlags flags = LLVMDIFlagZero;
@@ -107,7 +144,7 @@ gb_internal LLVMMetadataRef lb_debug_type_internal_proc(lbModule *m, Type *type)
flags = LLVMDIFlagNoReturn;
}
- return LLVMDIBuilderCreateSubroutineType(m->debug_builder, file, parameters, parameter_count, flags);
+ return LLVMDIBuilderCreateSubroutineType(m->debug_builder, file, parameters.data, cast(unsigned)parameters.count, flags);
}
gb_internal LLVMMetadataRef lb_debug_struct_field(lbModule *m, String const &name, Type *type, u64 offset_in_bits) {
diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp
index f6b9934ef..f20c52e88 100644
--- a/src/llvm_backend_expr.cpp
+++ b/src/llvm_backend_expr.cpp
@@ -705,31 +705,37 @@ gb_internal lbValue lb_emit_matrix_flatten(lbProcedure *p, lbValue m, Type *type
lbAddr res = lb_add_local_generated(p, type, true);
- i64 row_count = mt->Matrix.row_count;
- i64 column_count = mt->Matrix.column_count;
- TEMPORARY_ALLOCATOR_GUARD();
-
- auto srcs = array_make<lbValue>(temporary_allocator(), 0, row_count*column_count);
- auto dsts = array_make<lbValue>(temporary_allocator(), 0, row_count*column_count);
-
- for (i64 j = 0; j < column_count; j++) {
- for (i64 i = 0; i < row_count; i++) {
- lbValue src = lb_emit_matrix_ev(p, m, i, j);
- array_add(&srcs, src);
- }
- }
-
- for (i64 j = 0; j < column_count; j++) {
- for (i64 i = 0; i < row_count; i++) {
- lbValue dst = lb_emit_array_epi(p, res.addr, i + j*row_count);
- array_add(&dsts, dst);
- }
- }
-
- GB_ASSERT(srcs.count == dsts.count);
- for_array(i, srcs) {
- lb_emit_store(p, dsts[i], srcs[i]);
- }
+ GB_ASSERT(type_size_of(type) == type_size_of(m.type));
+
+ lbValue m_ptr = lb_address_from_load_or_generate_local(p, m);
+ lbValue n = lb_const_int(p->module, t_int, type_size_of(type));
+ lb_mem_copy_non_overlapping(p, res.addr, m_ptr, n);
+
+ // i64 row_count = mt->Matrix.row_count;
+ // i64 column_count = mt->Matrix.column_count;
+ // TEMPORARY_ALLOCATOR_GUARD();
+
+ // auto srcs = array_make<lbValue>(temporary_allocator(), 0, row_count*column_count);
+ // auto dsts = array_make<lbValue>(temporary_allocator(), 0, row_count*column_count);
+
+ // for (i64 j = 0; j < column_count; j++) {
+ // for (i64 i = 0; i < row_count; i++) {
+ // lbValue src = lb_emit_matrix_ev(p, m, i, j);
+ // array_add(&srcs, src);
+ // }
+ // }
+
+ // for (i64 j = 0; j < column_count; j++) {
+ // for (i64 i = 0; i < row_count; i++) {
+ // lbValue dst = lb_emit_array_epi(p, res.addr, i + j*row_count);
+ // array_add(&dsts, dst);
+ // }
+ // }
+
+ // GB_ASSERT(srcs.count == dsts.count);
+ // for_array(i, srcs) {
+ // lb_emit_store(p, dsts[i], srcs[i]);
+ // }
return lb_addr_load(p, res);
}
diff --git a/src/main.cpp b/src/main.cpp
index a03126caf..0a84b2f97 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -389,6 +389,7 @@ enum BuildFlagKind {
BuildFlag_PrintLinkerFlags,
// internal use only
+ BuildFlag_InternalFastISel,
BuildFlag_InternalIgnoreLazy,
BuildFlag_InternalIgnoreLLVMBuild,
BuildFlag_InternalIgnorePanic,
@@ -594,6 +595,7 @@ gb_internal bool parse_build_flags(Array<String> args) {
add_flag(&build_flags, BuildFlag_PrintLinkerFlags, str_lit("print-linker-flags"), BuildFlagParam_None, Command_build);
+ add_flag(&build_flags, BuildFlag_InternalFastISel, str_lit("internal-fast-isel"), BuildFlagParam_None, Command_all);
add_flag(&build_flags, BuildFlag_InternalIgnoreLazy, str_lit("internal-ignore-lazy"), BuildFlagParam_None, Command_all);
add_flag(&build_flags, BuildFlag_InternalIgnoreLLVMBuild, str_lit("internal-ignore-llvm-build"),BuildFlagParam_None, Command_all);
add_flag(&build_flags, BuildFlag_InternalIgnorePanic, str_lit("internal-ignore-panic"), BuildFlagParam_None, Command_all);
@@ -1408,6 +1410,9 @@ gb_internal bool parse_build_flags(Array<String> args) {
build_context.print_linker_flags = true;
break;
+ case BuildFlag_InternalFastISel:
+ build_context.fast_isel = true;
+ break;
case BuildFlag_InternalIgnoreLazy:
build_context.ignore_lazy = true;
break;
diff --git a/src/types.cpp b/src/types.cpp
index 63182f5c4..a9a7d6dda 100644
--- a/src/types.cpp
+++ b/src/types.cpp
@@ -1474,6 +1474,7 @@ gb_internal i64 matrix_align_of(Type *t, struct TypePath *tp) {
Type *elem = t->Matrix.elem;
i64 row_count = gb_max(t->Matrix.row_count, 1);
+ i64 column_count = gb_max(t->Matrix.column_count, 1);
bool pop = type_path_push(tp, elem);
if (tp->failure) {
@@ -1491,7 +1492,7 @@ gb_internal i64 matrix_align_of(Type *t, struct TypePath *tp) {
// could be maximally aligned but as a compromise, having no padding will be
// beneficial to third libraries that assume no padding
- i64 total_expected_size = row_count*t->Matrix.column_count*elem_size;
+ i64 total_expected_size = row_count*column_count*elem_size;
// i64 min_alignment = prev_pow2(elem_align * row_count);
i64 min_alignment = prev_pow2(total_expected_size);
while (total_expected_size != 0 && (total_expected_size % min_alignment) != 0) {
@@ -1523,12 +1524,15 @@ gb_internal i64 matrix_type_stride_in_bytes(Type *t, struct TypePath *tp) {
i64 stride_in_bytes = 0;
// NOTE(bill, 2021-10-25): The alignment strategy here is to have zero padding
- // It would be better for performance to pad each column so that each column
+ // It would be better for performance to pad each column/row so that each column/row
// could be maximally aligned but as a compromise, having no padding will be
// beneficial to third libraries that assume no padding
- i64 row_count = t->Matrix.row_count;
- stride_in_bytes = elem_size*row_count;
-
+
+ if (t->Matrix.is_row_major) {
+ stride_in_bytes = elem_size*t->Matrix.column_count;
+ } else {
+ stride_in_bytes = elem_size*t->Matrix.row_count;
+ }
t->Matrix.stride_in_bytes = stride_in_bytes;
return stride_in_bytes;
}
@@ -4217,7 +4221,11 @@ gb_internal i64 type_size_of_internal(Type *t, TypePath *path) {
case Type_Matrix: {
i64 stride_in_bytes = matrix_type_stride_in_bytes(t, path);
- return stride_in_bytes * t->Matrix.column_count;
+ if (t->Matrix.is_row_major) {
+ return stride_in_bytes * t->Matrix.row_count;
+ } else {
+ return stride_in_bytes * t->Matrix.column_count;
+ }
}
case Type_BitField: