mirror of
https://github.com/Ed94/Odin.git
synced 2026-07-17 16:31:25 -07:00
Merge remote-tracking branch 'offical/master'
This commit is contained in:
@@ -910,6 +910,7 @@ gb_internal void report_os_info() {
|
||||
{"23D60", {23, 3, 0}, "macOS", {"Sonoma", {14, 3, 1}}},
|
||||
{"23E214", {23, 4, 0}, "macOS", {"Sonoma", {14, 4, 0}}},
|
||||
{"23E224", {23, 4, 0}, "macOS", {"Sonoma", {14, 4, 1}}},
|
||||
{"23F79", {23, 5, 0}, "macOS", {"Sonoma", {14, 5, 0}}},
|
||||
};
|
||||
|
||||
|
||||
|
||||
+22
-6
@@ -1088,7 +1088,6 @@ gb_global TargetMetrics target_orca_wasm32 = {
|
||||
TargetArch_wasm32,
|
||||
4, 4, 8, 16,
|
||||
str_lit("wasm32-wasi-js"),
|
||||
// str_lit("e-m:e-p:32:32-i64:64-n32:64-S128"),
|
||||
};
|
||||
|
||||
|
||||
@@ -1138,6 +1137,14 @@ gb_global TargetMetrics target_freestanding_arm64 = {
|
||||
str_lit("aarch64-none-elf"),
|
||||
};
|
||||
|
||||
gb_global TargetMetrics target_freestanding_arm32 = {
|
||||
TargetOs_freestanding,
|
||||
TargetArch_arm32,
|
||||
4, 4, 4, 8,
|
||||
str_lit("arm-unknown-unknown-gnueabihf"),
|
||||
};
|
||||
|
||||
|
||||
struct NamedTargetMetrics {
|
||||
String name;
|
||||
TargetMetrics *metrics;
|
||||
@@ -1170,6 +1177,7 @@ gb_global NamedTargetMetrics named_targets[] = {
|
||||
{ str_lit("freestanding_wasm32"), &target_freestanding_wasm32 },
|
||||
{ str_lit("wasi_wasm32"), &target_wasi_wasm32 },
|
||||
{ str_lit("js_wasm32"), &target_js_wasm32 },
|
||||
{ str_lit("orca_wasm32"), &target_orca_wasm32 },
|
||||
|
||||
{ str_lit("freestanding_wasm64p32"), &target_freestanding_wasm64p32 },
|
||||
{ str_lit("js_wasm64p32"), &target_js_wasm64p32 },
|
||||
@@ -1179,6 +1187,7 @@ gb_global NamedTargetMetrics named_targets[] = {
|
||||
{ str_lit("freestanding_amd64_win64"), &target_freestanding_amd64_win64 },
|
||||
|
||||
{ str_lit("freestanding_arm64"), &target_freestanding_arm64 },
|
||||
{ str_lit("freestanding_arm32"), &target_freestanding_arm32 },
|
||||
};
|
||||
|
||||
gb_global NamedTargetMetrics *selected_target_metrics;
|
||||
@@ -2035,6 +2044,9 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta
|
||||
bc->link_flags = str_lit("/machine:x86 ");
|
||||
break;
|
||||
}
|
||||
} else if (bc->metrics.os == TargetOs_darwin) {
|
||||
bc->link_flags = concatenate3_strings(permanent_allocator(),
|
||||
str_lit("-target "), bc->metrics.target_triplet, str_lit(" "));
|
||||
} else if (is_arch_wasm()) {
|
||||
gbString link_flags = gb_string_make(heap_allocator(), " ");
|
||||
// link_flags = gb_string_appendc(link_flags, "--export-all ");
|
||||
@@ -2045,16 +2057,20 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta
|
||||
// }
|
||||
if (bc->no_entry_point || bc->metrics.os == TargetOs_orca) {
|
||||
link_flags = gb_string_appendc(link_flags, "--no-entry ");
|
||||
bc->no_entry_point = true; // just in case for the "orca" target
|
||||
}
|
||||
|
||||
|
||||
bc->link_flags = make_string_c(link_flags);
|
||||
|
||||
|
||||
// Disallow on wasm
|
||||
bc->use_separate_modules = false;
|
||||
} else {
|
||||
bc->link_flags = concatenate3_strings(permanent_allocator(),
|
||||
str_lit("-target "), bc->metrics.target_triplet, str_lit(" "));
|
||||
// NOTE: for targets other than darwin, we don't specify a `-target` link flag.
|
||||
// This is because we don't support cross-linking and clang is better at figuring
|
||||
// out what the actual target for linking is,
|
||||
// for example, on x86/alpine/musl it HAS to be `x86_64-alpine-linux-musl` to link correctly.
|
||||
//
|
||||
// Note that codegen will still target the triplet we specify, but the intricate details of
|
||||
// a target shouldn't matter as much to codegen (if it does at all) as it does to linking.
|
||||
}
|
||||
|
||||
// NOTE: needs to be done after adding the -target flag to the linker flags so the linker
|
||||
|
||||
+11
-23
@@ -2433,6 +2433,9 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As
|
||||
if (arg_count > max_count) {
|
||||
error(call, "Too many 'swizzle' indices, %td > %td", arg_count, max_count);
|
||||
return false;
|
||||
} else if (arg_count < 2) {
|
||||
error(call, "Not enough 'swizzle' indices, %td < 2", arg_count);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (type->kind == Type_Array) {
|
||||
@@ -5926,15 +5929,9 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As
|
||||
if (operand->mode != Addressing_Type) {
|
||||
error(operand->expr, "Expected a record type for '%.*s'", LIT(builtin_name));
|
||||
} else {
|
||||
Type *bt = base_type(operand->type);
|
||||
if (bt->kind == Type_Struct) {
|
||||
if (bt->Struct.polymorphic_params != nullptr) {
|
||||
operand->value = exact_value_i64(bt->Struct.polymorphic_params->Tuple.variables.count);
|
||||
}
|
||||
} else if (bt->kind == Type_Union) {
|
||||
if (bt->Union.polymorphic_params != nullptr) {
|
||||
operand->value = exact_value_i64(bt->Union.polymorphic_params->Tuple.variables.count);
|
||||
}
|
||||
TypeTuple *tuple = get_record_polymorphic_params(operand->type);
|
||||
if (tuple) {
|
||||
operand->value = exact_value_i64(tuple->variables.count);
|
||||
} else {
|
||||
error(operand->expr, "Expected a record type for '%.*s'", LIT(builtin_name));
|
||||
}
|
||||
@@ -5966,20 +5963,11 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As
|
||||
Entity *param = nullptr;
|
||||
i64 count = 0;
|
||||
|
||||
Type *bt = base_type(operand->type);
|
||||
if (bt->kind == Type_Struct) {
|
||||
if (bt->Struct.polymorphic_params != nullptr) {
|
||||
count = bt->Struct.polymorphic_params->Tuple.variables.count;
|
||||
if (index < count) {
|
||||
param = bt->Struct.polymorphic_params->Tuple.variables[cast(isize)index];
|
||||
}
|
||||
}
|
||||
} else if (bt->kind == Type_Union) {
|
||||
if (bt->Union.polymorphic_params != nullptr) {
|
||||
count = bt->Union.polymorphic_params->Tuple.variables.count;
|
||||
if (index < count) {
|
||||
param = bt->Union.polymorphic_params->Tuple.variables[cast(isize)index];
|
||||
}
|
||||
TypeTuple *tuple = get_record_polymorphic_params(operand->type);
|
||||
if (tuple) {
|
||||
count = tuple->variables.count;
|
||||
if (index < count) {
|
||||
param = tuple->variables[cast(isize)index];
|
||||
}
|
||||
} else {
|
||||
error(operand->expr, "Expected a specialized polymorphic record type for '%.*s'", LIT(builtin_name));
|
||||
|
||||
@@ -1264,6 +1264,9 @@ gb_internal void check_global_variable_decl(CheckerContext *ctx, Entity *&e, Ast
|
||||
if (ac.is_static) {
|
||||
error(e->token, "@(static) is not supported for global variables, nor required");
|
||||
}
|
||||
if (ac.rodata) {
|
||||
e->Variable.is_rodata = true;
|
||||
}
|
||||
ac.link_name = handle_link_name(ctx, e->token, ac.link_name, ac.link_prefix, ac.link_suffix);
|
||||
|
||||
if (is_arch_wasm() && e->Variable.thread_local_model.len != 0) {
|
||||
@@ -1350,6 +1353,9 @@ gb_internal void check_global_variable_decl(CheckerContext *ctx, Entity *&e, Ast
|
||||
Operand o = {};
|
||||
check_expr_with_type_hint(ctx, &o, init_expr, e->type);
|
||||
check_init_variable(ctx, e, &o, str_lit("variable declaration"));
|
||||
if (e->Variable.is_rodata && o.mode != Addressing_Constant) {
|
||||
error(o.expr, "Variables declared with @(rodata) must have constant initialization");
|
||||
}
|
||||
|
||||
check_rtti_type_disallowed(e->token, e->type, "A variable declaration is using a type, %s, which has been disallowed");
|
||||
}
|
||||
|
||||
+22
-11
@@ -281,8 +281,20 @@ gb_internal void error_operand_not_expression(Operand *o) {
|
||||
|
||||
gb_internal void error_operand_no_value(Operand *o) {
|
||||
if (o->mode == Addressing_NoValue) {
|
||||
gbString err = expr_to_string(o->expr);
|
||||
Ast *x = unparen_expr(o->expr);
|
||||
|
||||
if (x->kind == Ast_CallExpr) {
|
||||
Ast *p = unparen_expr(x->CallExpr.proc);
|
||||
if (p->kind == Ast_BasicDirective) {
|
||||
String tag = p->BasicDirective.name.string;
|
||||
if (tag == "panic" ||
|
||||
tag == "assert") {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gbString err = expr_to_string(o->expr);
|
||||
if (x->kind == Ast_CallExpr) {
|
||||
error(o->expr, "'%s' call does not return a value and cannot be used as a value", err);
|
||||
} else {
|
||||
@@ -3338,6 +3350,9 @@ gb_internal void check_cast(CheckerContext *c, Operand *x, Type *type) {
|
||||
if (is_type_untyped(x->type)) {
|
||||
Type *final_type = type;
|
||||
if (is_const_expr && !is_type_constant_type(type)) {
|
||||
if (is_type_union(type)) {
|
||||
convert_to_typed(c, x, type);
|
||||
}
|
||||
final_type = default_type(x->type);
|
||||
}
|
||||
update_untyped_expr_type(c, x->expr, final_type, true);
|
||||
@@ -4286,7 +4301,8 @@ gb_internal void convert_to_typed(CheckerContext *c, Operand *operand, Type *tar
|
||||
} else {
|
||||
switch (operand->type->Basic.kind) {
|
||||
case Basic_UntypedBool:
|
||||
if (!is_type_boolean(target_type)) {
|
||||
if (!is_type_boolean(target_type) &&
|
||||
!is_type_integer(target_type)) {
|
||||
operand->mode = Addressing_Invalid;
|
||||
convert_untyped_error(c, operand, target_type);
|
||||
return;
|
||||
@@ -7331,14 +7347,9 @@ gb_internal CallArgumentError check_polymorphic_record_type(CheckerContext *c, O
|
||||
gbString s = gb_string_make_reserve(heap_allocator(), e->token.string.len+3);
|
||||
s = gb_string_append_fmt(s, "%.*s(", LIT(e->token.string));
|
||||
|
||||
Type *params = nullptr;
|
||||
switch (bt->kind) {
|
||||
case Type_Struct: params = bt->Struct.polymorphic_params; break;
|
||||
case Type_Union: params = bt->Union.polymorphic_params; break;
|
||||
}
|
||||
|
||||
if (params != nullptr) for_array(i, params->Tuple.variables) {
|
||||
Entity *v = params->Tuple.variables[i];
|
||||
TypeTuple *tuple = get_record_polymorphic_params(e->type);
|
||||
if (tuple != nullptr) for_array(i, tuple->variables) {
|
||||
Entity *v = tuple->variables[i];
|
||||
String name = v->token.string;
|
||||
if (i > 0) {
|
||||
s = gb_string_append_fmt(s, ", ");
|
||||
@@ -8344,7 +8355,7 @@ gb_internal ExprKind check_basic_directive_expr(CheckerContext *c, Operand *o, A
|
||||
name == "assert" ||
|
||||
name == "defined" ||
|
||||
name == "config" ||
|
||||
name == "exists" ||
|
||||
name == "exists" ||
|
||||
name == "load" ||
|
||||
name == "load_hash" ||
|
||||
name == "load_directory" ||
|
||||
|
||||
+14
-2
@@ -501,6 +501,9 @@ gb_internal Type *check_assignment_variable(CheckerContext *ctx, Operand *lhs, O
|
||||
return nullptr;
|
||||
|
||||
case Addressing_Variable:
|
||||
if (e && e->kind == Entity_Variable && e->Variable.is_rodata) {
|
||||
error(lhs->expr, "Assignment to variable '%.*s' marked as @(rodata) is not allowed", LIT(e->token.string));
|
||||
}
|
||||
break;
|
||||
|
||||
case Addressing_MapIndex: {
|
||||
@@ -1252,8 +1255,6 @@ gb_internal void check_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags
|
||||
error_line("\t%.*s\n", LIT(f->token.string));
|
||||
}
|
||||
}
|
||||
error_line("\n");
|
||||
|
||||
error_line("\tSuggestion: Was '#partial switch' wanted?\n");
|
||||
}
|
||||
}
|
||||
@@ -2055,6 +2056,13 @@ gb_internal void check_value_decl_stmt(CheckerContext *ctx, Ast *node, u32 mod_f
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ac.rodata) {
|
||||
if (ac.is_static) {
|
||||
e->Variable.is_rodata = true;
|
||||
} else {
|
||||
error(e->token, "Only global or @(static) variables can have @(rodata) applied");
|
||||
}
|
||||
}
|
||||
if (ac.thread_local_model != "") {
|
||||
String name = e->token.string;
|
||||
if (name == "_") {
|
||||
@@ -2493,6 +2501,10 @@ gb_internal void check_return_stmt(CheckerContext *ctx, Ast *node) {
|
||||
unsafe_return_error(o, "the address of an indexed variable", f->type);
|
||||
}
|
||||
}
|
||||
} else if (o.mode == Addressing_Constant && is_type_slice(o.type)) {
|
||||
ERROR_BLOCK();
|
||||
unsafe_return_error(o, "a compound literal of a slice");
|
||||
error_line("\tNote: A constant slice value will use the memory of the current stack frame\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+10
-18
@@ -564,19 +564,7 @@ gb_internal bool check_record_poly_operand_specialization(CheckerContext *ctx, T
|
||||
gb_internal Entity *find_polymorphic_record_entity(GenTypesData *found_gen_types, isize param_count, Array<Operand> const &ordered_operands) {
|
||||
for (Entity *e : found_gen_types->types) {
|
||||
Type *t = base_type(e->type);
|
||||
TypeTuple *tuple = nullptr;
|
||||
switch (t->kind) {
|
||||
case Type_Struct:
|
||||
if (t->Struct.polymorphic_params) {
|
||||
tuple = &t->Struct.polymorphic_params->Tuple;
|
||||
}
|
||||
break;
|
||||
case Type_Union:
|
||||
if (t->Union.polymorphic_params) {
|
||||
tuple = &t->Union.polymorphic_params->Tuple;
|
||||
}
|
||||
break;
|
||||
}
|
||||
TypeTuple *tuple = get_record_polymorphic_params(t);
|
||||
GB_ASSERT_MSG(tuple != nullptr, "%s :: %s", type_to_string(e->type), type_to_string(t));
|
||||
GB_ASSERT(param_count == tuple->variables.count);
|
||||
|
||||
@@ -663,6 +651,8 @@ gb_internal void check_struct_type(CheckerContext *ctx, Type *struct_type, Ast *
|
||||
&struct_type->Struct.is_polymorphic,
|
||||
node, poly_operands
|
||||
);
|
||||
wait_signal_set(&struct_type->Struct.polymorphic_wait_signal);
|
||||
|
||||
struct_type->Struct.is_poly_specialized = check_record_poly_operand_specialization(ctx, struct_type, poly_operands, &struct_type->Struct.is_polymorphic);
|
||||
if (original_type_for_poly) {
|
||||
GB_ASSERT(named_type != nullptr);
|
||||
@@ -712,6 +702,8 @@ gb_internal void check_union_type(CheckerContext *ctx, Type *union_type, Ast *no
|
||||
&union_type->Union.is_polymorphic,
|
||||
node, poly_operands
|
||||
);
|
||||
wait_signal_set(&union_type->Union.polymorphic_wait_signal);
|
||||
|
||||
union_type->Union.is_poly_specialized = check_record_poly_operand_specialization(ctx, union_type, poly_operands, &union_type->Union.is_polymorphic);
|
||||
if (original_type_for_poly) {
|
||||
GB_ASSERT(named_type != nullptr);
|
||||
@@ -784,7 +776,7 @@ gb_internal void check_union_type(CheckerContext *ctx, Type *union_type, Ast *no
|
||||
}
|
||||
}
|
||||
if (variants.count < 2) {
|
||||
error(ut->align, "A union with #no_nil must have at least 2 variants");
|
||||
error(node, "A union with #no_nil must have at least 2 variants");
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -1457,8 +1449,8 @@ gb_internal bool check_type_specialization_to(CheckerContext *ctx, Type *special
|
||||
s->Struct.polymorphic_params != nullptr &&
|
||||
t->Struct.polymorphic_params != nullptr) {
|
||||
|
||||
TypeTuple *s_tuple = &s->Struct.polymorphic_params->Tuple;
|
||||
TypeTuple *t_tuple = &t->Struct.polymorphic_params->Tuple;
|
||||
TypeTuple *s_tuple = get_record_polymorphic_params(s);
|
||||
TypeTuple *t_tuple = get_record_polymorphic_params(t);
|
||||
GB_ASSERT(t_tuple->variables.count == s_tuple->variables.count);
|
||||
for_array(i, s_tuple->variables) {
|
||||
Entity *s_e = s_tuple->variables[i];
|
||||
@@ -1510,8 +1502,8 @@ gb_internal bool check_type_specialization_to(CheckerContext *ctx, Type *special
|
||||
s->Union.polymorphic_params != nullptr &&
|
||||
t->Union.polymorphic_params != nullptr) {
|
||||
|
||||
TypeTuple *s_tuple = &s->Union.polymorphic_params->Tuple;
|
||||
TypeTuple *t_tuple = &t->Union.polymorphic_params->Tuple;
|
||||
TypeTuple *s_tuple = get_record_polymorphic_params(s);
|
||||
TypeTuple *t_tuple = get_record_polymorphic_params(t);
|
||||
GB_ASSERT(t_tuple->variables.count == s_tuple->variables.count);
|
||||
for_array(i, s_tuple->variables) {
|
||||
Entity *s_e = s_tuple->variables[i];
|
||||
|
||||
@@ -3628,6 +3628,12 @@ gb_internal DECL_ATTRIBUTE_PROC(var_decl_attribute) {
|
||||
}
|
||||
ac->is_static = true;
|
||||
return true;
|
||||
} else if (name == "rodata") {
|
||||
if (value != nullptr) {
|
||||
error(elem, "'rodata' does not have any parameters");
|
||||
}
|
||||
ac->rodata = true;
|
||||
return true;
|
||||
} else if (name == "thread_local") {
|
||||
ExactValue ev = check_decl_attribute_value(c, value);
|
||||
if (ac->init_expr_list_count > 0) {
|
||||
|
||||
@@ -133,6 +133,7 @@ struct AttributeContext {
|
||||
bool entry_point_only : 1;
|
||||
bool instrumentation_enter : 1;
|
||||
bool instrumentation_exit : 1;
|
||||
bool rodata : 1;
|
||||
u32 optimization_mode; // ProcedureOptimizationMode
|
||||
i64 foreign_import_priority_index;
|
||||
String extra_linker_flags;
|
||||
|
||||
@@ -230,6 +230,7 @@ struct Entity {
|
||||
bool is_foreign;
|
||||
bool is_export;
|
||||
bool is_global;
|
||||
bool is_rodata;
|
||||
} Variable;
|
||||
struct {
|
||||
Type * type_parameter_specialization;
|
||||
|
||||
+33
-32
@@ -390,8 +390,6 @@ gb_internal void error_va(TokenPos const &pos, TokenPos end, char const *fmt, va
|
||||
error_out_empty();
|
||||
} else {
|
||||
error_out_pos(pos);
|
||||
}
|
||||
if (has_ansi_terminal_colours()) {
|
||||
error_out_coloured("Error: ", TerminalStyle_Normal, TerminalColour_Red);
|
||||
}
|
||||
error_out_va(fmt, va);
|
||||
@@ -407,29 +405,31 @@ gb_internal void warning_va(TokenPos const &pos, TokenPos end, char const *fmt,
|
||||
error_va(pos, end, fmt, va);
|
||||
return;
|
||||
}
|
||||
if (global_ignore_warnings()) {
|
||||
return;
|
||||
}
|
||||
|
||||
global_error_collector.warning_count.fetch_add(1);
|
||||
mutex_lock(&global_error_collector.mutex);
|
||||
|
||||
push_error_value(pos, ErrorValue_Warning);
|
||||
|
||||
if (!global_ignore_warnings()) {
|
||||
if (pos.line == 0) {
|
||||
if (pos.line == 0) {
|
||||
error_out_empty();
|
||||
error_out_coloured("Warning: ", TerminalStyle_Normal, TerminalColour_Yellow);
|
||||
error_out_va(fmt, va);
|
||||
error_out("\n");
|
||||
} else {
|
||||
// global_error_collector.prev = pos;
|
||||
if (json_errors()) {
|
||||
error_out_empty();
|
||||
error_out_coloured("Warning: ", TerminalStyle_Normal, TerminalColour_Yellow);
|
||||
error_out_va(fmt, va);
|
||||
error_out("\n");
|
||||
} else {
|
||||
// global_error_collector.prev = pos;
|
||||
if (json_errors()) {
|
||||
error_out_empty();
|
||||
} else {
|
||||
error_out_pos(pos);
|
||||
}
|
||||
error_out_pos(pos);
|
||||
error_out_coloured("Warning: ", TerminalStyle_Normal, TerminalColour_Yellow);
|
||||
error_out_va(fmt, va);
|
||||
error_out("\n");
|
||||
show_error_on_line(pos, end);
|
||||
}
|
||||
error_out_va(fmt, va);
|
||||
error_out("\n");
|
||||
show_error_on_line(pos, end);
|
||||
}
|
||||
try_pop_error_value();
|
||||
mutex_unlock(&global_error_collector.mutex);
|
||||
@@ -544,30 +544,31 @@ gb_internal void syntax_warning_va(TokenPos const &pos, TokenPos end, char const
|
||||
syntax_error_va(pos, end, fmt, va);
|
||||
return;
|
||||
}
|
||||
if (global_ignore_warnings()) {
|
||||
return;
|
||||
}
|
||||
mutex_lock(&global_error_collector.mutex);
|
||||
global_error_collector.warning_count++;
|
||||
|
||||
|
||||
push_error_value(pos, ErrorValue_Warning);
|
||||
|
||||
if (!global_ignore_warnings()) {
|
||||
if (pos.line == 0) {
|
||||
if (pos.line == 0) {
|
||||
error_out_empty();
|
||||
error_out_coloured("Syntax Warning: ", TerminalStyle_Normal, TerminalColour_Yellow);
|
||||
error_out_va(fmt, va);
|
||||
error_out("\n");
|
||||
} else {
|
||||
// global_error_collector.prev = pos;
|
||||
if (json_errors()) {
|
||||
error_out_empty();
|
||||
error_out_coloured("Syntax Warning: ", TerminalStyle_Normal, TerminalColour_Yellow);
|
||||
error_out_va(fmt, va);
|
||||
error_out("\n");
|
||||
} else {
|
||||
// global_error_collector.prev = pos;
|
||||
if (json_errors()) {
|
||||
error_out_empty();
|
||||
} else {
|
||||
error_out_pos(pos);
|
||||
}
|
||||
error_out_coloured("Syntax Warning: ", TerminalStyle_Normal, TerminalColour_Yellow);
|
||||
error_out_va(fmt, va);
|
||||
error_out("\n");
|
||||
// show_error_on_line(pos, end);
|
||||
error_out_pos(pos);
|
||||
}
|
||||
error_out_coloured("Syntax Warning: ", TerminalStyle_Normal, TerminalColour_Yellow);
|
||||
error_out_va(fmt, va);
|
||||
error_out("\n");
|
||||
// show_error_on_line(pos, end);
|
||||
}
|
||||
|
||||
try_pop_error_value();
|
||||
@@ -838,4 +839,4 @@ gb_internal void print_all_errors(void) {
|
||||
gb_file_write(f, res, gb_string_length(res));
|
||||
|
||||
errors_already_printed = true;
|
||||
}
|
||||
}
|
||||
|
||||
+29
-15
@@ -13,6 +13,7 @@ struct LinkerData {
|
||||
};
|
||||
|
||||
gb_internal i32 system_exec_command_line_app(char const *name, char const *fmt, ...);
|
||||
gb_internal bool system_exec_command_line_app_output(char const *command, gbString *output);
|
||||
|
||||
#if defined(GB_SYSTEM_OSX)
|
||||
gb_internal void linker_enable_system_library_linking(LinkerData *ld) {
|
||||
@@ -69,27 +70,40 @@ gb_internal i32 linker_stage(LinkerData *gen) {
|
||||
if (is_arch_wasm()) {
|
||||
timings_start_section(timings, str_lit("wasm-ld"));
|
||||
|
||||
String extra_orca_flags = {};
|
||||
gbString extra_orca_flags = gb_string_make(temporary_allocator(), "");
|
||||
|
||||
gbString inputs = gb_string_make(temporary_allocator(), "");
|
||||
inputs = gb_string_append_fmt(inputs, "\"%.*s.o\"", LIT(output_filename));
|
||||
|
||||
#if defined(GB_SYSTEM_WINDOWS)
|
||||
if (build_context.metrics.os == TargetOs_orca) {
|
||||
extra_orca_flags = str_lit(" W:/orca/installation/dev-afb9591/bin/liborca_wasm.a --export-dynamic");
|
||||
gbString orca_sdk_path = gb_string_make(temporary_allocator(), "");
|
||||
if (!system_exec_command_line_app_output("orca sdk-path", &orca_sdk_path)) {
|
||||
gb_printf_err("executing `orca sdk-path` failed, make sure Orca is installed and added to your path\n");
|
||||
return 1;
|
||||
}
|
||||
if (gb_string_length(orca_sdk_path) == 0) {
|
||||
gb_printf_err("executing `orca sdk-path` did not produce output\n");
|
||||
return 1;
|
||||
}
|
||||
inputs = gb_string_append_fmt(inputs, " \"%s/orca-libc/lib/crt1.o\" \"%s/orca-libc/lib/libc.o\"", orca_sdk_path, orca_sdk_path);
|
||||
|
||||
extra_orca_flags = gb_string_append_fmt(extra_orca_flags, " -L \"%s/bin\" -lorca_wasm --export-dynamic", orca_sdk_path);
|
||||
}
|
||||
|
||||
result = system_exec_command_line_app("wasm-ld",
|
||||
"\"%.*s\\bin\\wasm-ld\" \"%.*s.o\" -o \"%.*s\" %.*s %.*s %.*s",
|
||||
LIT(build_context.ODIN_ROOT),
|
||||
LIT(output_filename), LIT(output_filename), LIT(build_context.link_flags), LIT(build_context.extra_linker_flags),
|
||||
LIT(extra_orca_flags));
|
||||
#else
|
||||
if (build_context.metrics.os == TargetOs_orca) {
|
||||
extra_orca_flags = str_lit(" -L . -lorca --export-dynamic");
|
||||
}
|
||||
|
||||
#if defined(GB_SYSTEM_WINDOWS)
|
||||
result = system_exec_command_line_app("wasm-ld",
|
||||
"wasm-ld \"%.*s.o\" -o \"%.*s\" %.*s %.*s %.*s",
|
||||
LIT(output_filename), LIT(output_filename), LIT(build_context.link_flags), LIT(build_context.extra_linker_flags),
|
||||
LIT(extra_orca_flags));
|
||||
"\"%.*s\\bin\\wasm-ld\" %s -o \"%.*s\" %.*s %.*s %s",
|
||||
LIT(build_context.ODIN_ROOT),
|
||||
inputs, LIT(output_filename), LIT(build_context.link_flags), LIT(build_context.extra_linker_flags),
|
||||
extra_orca_flags);
|
||||
#else
|
||||
result = system_exec_command_line_app("wasm-ld",
|
||||
"wasm-ld %s -o \"%.*s\" %.*s %.*s %s",
|
||||
inputs, LIT(output_filename),
|
||||
LIT(build_context.link_flags),
|
||||
LIT(build_context.extra_linker_flags),
|
||||
extra_orca_flags);
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
+9
-1
@@ -900,7 +900,15 @@ namespace lbAbiAmd64SysV {
|
||||
}
|
||||
|
||||
switch (LLVMGetTypeKind(t)) {
|
||||
case LLVMIntegerTypeKind:
|
||||
case LLVMIntegerTypeKind: {
|
||||
i64 s = t_size;
|
||||
while (s > 0) {
|
||||
unify(cls, ix + off/8, RegClass_Int);
|
||||
off += 8;
|
||||
s -= 8;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case LLVMPointerTypeKind:
|
||||
case LLVMHalfTypeKind:
|
||||
unify(cls, ix + off/8, RegClass_Int);
|
||||
|
||||
+18
-2
@@ -1160,6 +1160,10 @@ gb_internal lbProcedure *lb_create_startup_runtime(lbModule *main_module, lbProc
|
||||
if (is_type_untyped_nil(init.type)) {
|
||||
LLVMSetInitializer(var.var.value, LLVMConstNull(global_type));
|
||||
var.is_initialized = true;
|
||||
|
||||
if (e->Variable.is_rodata) {
|
||||
LLVMSetGlobalConstant(var.var.value, true);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
GB_PANIC("Invalid init value, got %s", expr_to_string(init_expr));
|
||||
@@ -1174,6 +1178,10 @@ gb_internal lbProcedure *lb_create_startup_runtime(lbModule *main_module, lbProc
|
||||
}
|
||||
LLVMSetInitializer(var.var.value, init.value);
|
||||
var.is_initialized = true;
|
||||
|
||||
if (e->Variable.is_rodata) {
|
||||
LLVMSetGlobalConstant(var.var.value, true);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
@@ -1206,8 +1214,9 @@ gb_internal lbProcedure *lb_create_startup_runtime(lbModule *main_module, lbProc
|
||||
|
||||
var.is_initialized = true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
CheckerInfo *info = main_module->gen->info;
|
||||
|
||||
for (Entity *e : info->init_procedures) {
|
||||
@@ -3210,14 +3219,21 @@ gb_internal bool lb_generate_code(lbGenerator *gen) {
|
||||
lbValue init = lb_const_value(m, tav.type, v);
|
||||
LLVMSetInitializer(g.value, init.value);
|
||||
var.is_initialized = true;
|
||||
if (e->kind == Entity_Variable && e->Variable.is_rodata) {
|
||||
LLVMSetGlobalConstant(g.value, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!var.is_initialized && is_type_untyped_nil(tav.type)) {
|
||||
var.is_initialized = true;
|
||||
if (e->kind == Entity_Variable && e->Variable.is_rodata) {
|
||||
LLVMSetGlobalConstant(g.value, true);
|
||||
}
|
||||
}
|
||||
} else if (e->kind == Entity_Variable && e->Variable.is_rodata) {
|
||||
LLVMSetGlobalConstant(g.value, true);
|
||||
}
|
||||
|
||||
array_add(&global_variables, var);
|
||||
|
||||
lb_add_entity(m, e, g);
|
||||
|
||||
@@ -504,6 +504,10 @@ gb_internal bool lb_is_matrix_simdable(Type *t) {
|
||||
if ((mt->Matrix.row_count & 1) ^ (mt->Matrix.column_count & 1)) {
|
||||
return false;
|
||||
}
|
||||
if (mt->Matrix.is_row_major) {
|
||||
// TODO(bill): make #row_major matrices work with SIMD
|
||||
return false;
|
||||
}
|
||||
|
||||
if (elem->kind == Type_Basic) {
|
||||
switch (elem->Basic.kind) {
|
||||
@@ -1869,13 +1873,40 @@ gb_internal lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) {
|
||||
lbValue res_i128 = lb_emit_runtime_call(p, call, args);
|
||||
return lb_emit_conv(p, res_i128, t);
|
||||
}
|
||||
i64 sz = type_size_of(src);
|
||||
|
||||
lbValue res = {};
|
||||
res.type = t;
|
||||
if (is_type_unsigned(dst)) {
|
||||
res.value = LLVMBuildFPToUI(p->builder, value.value, lb_type(m, t), "");
|
||||
switch (sz) {
|
||||
case 2:
|
||||
case 4:
|
||||
res.value = LLVMBuildFPToUI(p->builder, value.value, lb_type(m, t_u32), "");
|
||||
res.value = LLVMBuildIntCast2(p->builder, res.value, lb_type(m, t), false, "");
|
||||
break;
|
||||
case 8:
|
||||
res.value = LLVMBuildFPToUI(p->builder, value.value, lb_type(m, t_u64), "");
|
||||
res.value = LLVMBuildIntCast2(p->builder, res.value, lb_type(m, t), false, "");
|
||||
break;
|
||||
default:
|
||||
GB_PANIC("Unhandled float type");
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
res.value = LLVMBuildFPToSI(p->builder, value.value, lb_type(m, t), "");
|
||||
switch (sz) {
|
||||
case 2:
|
||||
case 4:
|
||||
res.value = LLVMBuildFPToSI(p->builder, value.value, lb_type(m, t_i32), "");
|
||||
res.value = LLVMBuildIntCast2(p->builder, res.value, lb_type(m, t), true, "");
|
||||
break;
|
||||
case 8:
|
||||
res.value = LLVMBuildFPToSI(p->builder, value.value, lb_type(m, t_i64), "");
|
||||
res.value = LLVMBuildIntCast2(p->builder, res.value, lb_type(m, t), true, "");
|
||||
break;
|
||||
default:
|
||||
GB_PANIC("Unhandled float type");
|
||||
break;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -1383,8 +1383,6 @@ 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)) {
|
||||
LLVMSetAlignment(res.addr.value, cast(unsigned)lb_alignof(vector_type));
|
||||
|
||||
LLVMValueRef vp = LLVMBuildPointerCast(p->builder, addr.addr.value, LLVMPointerType(vector_type, 0), "");
|
||||
LLVMValueRef v = LLVMBuildLoad2(p->builder, vector_type, vp, "");
|
||||
LLVMValueRef scalars[4] = {};
|
||||
@@ -1394,6 +1392,8 @@ gb_internal lbValue lb_addr_load(lbProcedure *p, lbAddr const &addr) {
|
||||
LLVMValueRef mask = LLVMConstVector(scalars, addr.swizzle.count);
|
||||
LLVMValueRef sv = llvm_basic_shuffle(p, v, mask);
|
||||
|
||||
LLVMSetAlignment(res.addr.value, cast(unsigned)lb_alignof(LLVMTypeOf(sv)));
|
||||
|
||||
LLVMValueRef dst = LLVMBuildPointerCast(p->builder, ptr.value, LLVMPointerType(LLVMTypeOf(sv), 0), "");
|
||||
LLVMBuildStore(p->builder, sv, dst);
|
||||
} else {
|
||||
|
||||
@@ -710,13 +710,12 @@ gb_internal void lb_begin_procedure_body(lbProcedure *p) {
|
||||
lb_set_debug_position_to_procedure_begin(p);
|
||||
if (p->debug_info != nullptr) {
|
||||
if (p->context_stack.count != 0) {
|
||||
lbBlock *prev_block = p->curr_block;
|
||||
p->curr_block = p->decl_block;
|
||||
lb_add_debug_context_variable(p, lb_find_or_generate_context_ptr(p));
|
||||
p->curr_block = prev_block;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
lb_start_block(p, p->entry_block);
|
||||
}
|
||||
|
||||
gb_internal void lb_end_procedure_body(lbProcedure *p) {
|
||||
|
||||
@@ -1850,7 +1850,9 @@ gb_internal void lb_build_static_variables(lbProcedure *p, AstValueDecl *vd) {
|
||||
LLVMSetInitializer(global, LLVMConstNull(lb_type(p->module, e->type)));
|
||||
if (value.value != nullptr) {
|
||||
LLVMSetInitializer(global, value.value);
|
||||
} else {
|
||||
}
|
||||
if (e->Variable.is_rodata) {
|
||||
LLVMSetGlobalConstant(global, true);
|
||||
}
|
||||
if (e->Variable.thread_local_model != "") {
|
||||
LLVMSetThreadLocal(global, true);
|
||||
|
||||
@@ -155,6 +155,38 @@ gb_internal i32 system_exec_command_line_app(char const *name, char const *fmt,
|
||||
return exit_code;
|
||||
}
|
||||
|
||||
#if defined(GB_SYSTEM_WINDOWS)
|
||||
#define popen _popen
|
||||
#define pclose _pclose
|
||||
#endif
|
||||
|
||||
gb_internal bool system_exec_command_line_app_output(char const *command, gbString *output) {
|
||||
GB_ASSERT(output);
|
||||
|
||||
u8 buffer[256];
|
||||
FILE *stream;
|
||||
stream = popen(command, "r");
|
||||
if (!stream) {
|
||||
return false;
|
||||
}
|
||||
defer (pclose(stream));
|
||||
|
||||
while (!feof(stream)) {
|
||||
size_t n = fread(buffer, 1, 255, stream);
|
||||
*output = gb_string_append_length(*output, buffer, n);
|
||||
|
||||
if (ferror(stream)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (build_context.show_system_calls) {
|
||||
gb_printf_err("[SYSTEM CALL OUTPUT] %s -> %s\n", command, *output);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
gb_internal Array<String> setup_args(int argc, char const **argv) {
|
||||
gbAllocator a = heap_allocator();
|
||||
|
||||
|
||||
+8
-2
@@ -140,6 +140,7 @@ struct TypeStruct {
|
||||
i64 custom_field_align;
|
||||
Type * polymorphic_params; // Type_Tuple
|
||||
Type * polymorphic_parent;
|
||||
Wait_Signal polymorphic_wait_signal;
|
||||
|
||||
Type * soa_elem;
|
||||
i32 soa_count;
|
||||
@@ -167,6 +168,7 @@ struct TypeUnion {
|
||||
i64 custom_align;
|
||||
Type * polymorphic_params; // Type_Tuple
|
||||
Type * polymorphic_parent;
|
||||
Wait_Signal polymorphic_wait_signal;
|
||||
|
||||
i16 tag_size;
|
||||
bool is_polymorphic;
|
||||
@@ -1093,6 +1095,7 @@ gb_internal Type *alloc_type_struct() {
|
||||
gb_internal Type *alloc_type_struct_complete() {
|
||||
Type *t = alloc_type(Type_Struct);
|
||||
wait_signal_set(&t->Struct.fields_wait_signal);
|
||||
wait_signal_set(&t->Struct.polymorphic_wait_signal);
|
||||
return t;
|
||||
}
|
||||
|
||||
@@ -1491,10 +1494,10 @@ gb_internal i64 matrix_align_of(Type *t, struct TypePath *tp) {
|
||||
i64 total_expected_size = row_count*t->Matrix.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 % min_alignment) != 0) {
|
||||
while (total_expected_size != 0 && (total_expected_size % min_alignment) != 0) {
|
||||
min_alignment >>= 1;
|
||||
}
|
||||
GB_ASSERT(min_alignment >= elem_align);
|
||||
min_alignment = gb_max(min_alignment, elem_align);
|
||||
|
||||
i64 align = gb_min(min_alignment, build_context.max_simd_align);
|
||||
return align;
|
||||
@@ -2136,15 +2139,18 @@ gb_internal bool is_type_polymorphic_record_unspecialized(Type *t) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
gb_internal TypeTuple *get_record_polymorphic_params(Type *t) {
|
||||
t = base_type(t);
|
||||
switch (t->kind) {
|
||||
case Type_Struct:
|
||||
wait_signal_until_available(&t->Struct.polymorphic_wait_signal);
|
||||
if (t->Struct.polymorphic_params) {
|
||||
return &t->Struct.polymorphic_params->Tuple;
|
||||
}
|
||||
break;
|
||||
case Type_Union:
|
||||
wait_signal_until_available(&t->Union.polymorphic_wait_signal);
|
||||
if (t->Union.polymorphic_params) {
|
||||
return &t->Union.polymorphic_params->Tuple;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user