Merge remote-tracking branch 'offical/master'

This commit is contained in:
ed
2024-06-11 19:23:35 -04:00
30 changed files with 466 additions and 189 deletions
+46
View File
@@ -1857,6 +1857,7 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As
case BuiltinProc_objc_register_class:
case BuiltinProc_atomic_type_is_lock_free:
case BuiltinProc_has_target_feature:
case BuiltinProc_procedure_of:
// NOTE(bill): The first arg may be a Type, this will be checked case by case
break;
@@ -6171,6 +6172,51 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As
break;
}
case BuiltinProc_procedure_of:
{
Ast *call_expr = unparen_expr(ce->args[0]);
Operand op = {};
check_expr_base(c, &op, ce->args[0], nullptr);
if (op.mode != Addressing_Value && !(call_expr && call_expr->kind == Ast_CallExpr)) {
error(ce->args[0], "Expected a call expression for '%.*s'", LIT(builtin_name));
return false;
}
Ast *proc = call_expr->CallExpr.proc;
Entity *e = entity_of_node(proc);
if (e == nullptr) {
error(ce->args[0], "Invalid procedure value, expected a regular/specialized procedure");
return false;
}
TypeAndValue tav = proc->tav;
operand->type = e->type;
operand->mode = Addressing_Value;
operand->value = tav.value;
operand->builtin_id = BuiltinProc_Invalid;
operand->proc_group = nullptr;
if (tav.mode == Addressing_Builtin) {
operand->mode = tav.mode;
operand->builtin_id = cast(BuiltinProcId)e->Builtin.id;
break;
}
if (!is_type_proc(e->type)) {
gbString s = type_to_string(e->type);
error(ce->args[0], "Expected a procedure value, got '%s'", s);
gb_string_free(s);
return false;
}
ce->entity_procedure_of = e;
break;
}
case BuiltinProc_constant_utf16_cstring:
{
String value = {};
+23 -6
View File
@@ -88,11 +88,17 @@ gb_internal Type *check_init_variable(CheckerContext *ctx, Entity *e, Operand *o
e->type = t_invalid;
return nullptr;
} else if (is_type_polymorphic(t)) {
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));
e->type = t_invalid;
return nullptr;
Entity *e = entity_of_node(operand->expr);
if (e == nullptr) {
return nullptr;
}
if (e->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));
e->type = t_invalid;
return nullptr;
}
} else if (is_type_empty_union(t)) {
gbString str = type_to_string(t);
defer (gb_string_free(str));
@@ -479,6 +485,9 @@ gb_internal void check_const_decl(CheckerContext *ctx, Entity *e, Ast *type_expr
entity = check_selector(ctx, &operand, init, e->type);
} else {
check_expr_or_type(ctx, &operand, init, e->type);
if (init->kind == Ast_CallExpr) {
entity = init->CallExpr.entity_procedure_of;
}
}
switch (operand.mode) {
@@ -526,6 +535,7 @@ gb_internal void check_const_decl(CheckerContext *ctx, Entity *e, Ast *type_expr
return;
}
if (entity != nullptr) {
if (e->type != nullptr) {
Operand x = {};
@@ -1135,7 +1145,14 @@ gb_internal void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) {
}
if (ac.link_name.len > 0) {
e->Procedure.link_name = ac.link_name;
String ln = ac.link_name;
e->Procedure.link_name = ln;
if (ln == "memcpy" ||
ln == "memmove" ||
ln == "mem_copy" ||
ln == "mem_copy_non_overlapping") {
e->Procedure.is_memcpy_like = true;
}
}
if (ac.deferred_procedure.entity != nullptr) {
+2 -1
View File
@@ -578,6 +578,7 @@ gb_internal bool find_or_generate_polymorphic_procedure(CheckerContext *old_c, E
d->defer_use_checked = false;
Entity *entity = alloc_entity_procedure(nullptr, token, final_proc_type, tags);
entity->state.store(EntityState_Resolved);
entity->identifier = ident;
add_entity_and_decl_info(&nctx, ident, entity, d);
@@ -7674,7 +7675,7 @@ gb_internal ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *c
if (decl->proc_lit) {
ast_node(pl, ProcLit, decl->proc_lit);
if (pl->inlining == ProcInlining_no_inline) {
error(call, "'#force_inline' cannot be applied to a procedure that has be marked as '#force_no_inline'");
error(call, "'#force_inline' cannot be applied to a procedure that has been marked as '#force_no_inline'");
}
}
}
+9 -1
View File
@@ -2224,8 +2224,16 @@ gb_internal void check_expr_stmt(CheckerContext *ctx, Ast *node) {
}
if (do_require) {
gbString expr_str = expr_to_string(ce->proc);
defer (gb_string_free(expr_str));
if (builtin_id) {
String real_name = builtin_procs[builtin_id].name;
if (real_name != make_string(cast(u8 const *)expr_str, gb_string_length(expr_str))) {
error(node, "'%s' ('%.*s.%.*s') requires that its results must be handled", expr_str,
LIT(builtin_proc_pkg_name[builtin_procs[builtin_id].pkg]), LIT(real_name));
return;
}
}
error(node, "'%s' requires that its results must be handled", expr_str);
gb_string_free(expr_str);
}
return;
} else if (expr && expr->kind == Ast_SelectorCallExpr) {
+31
View File
@@ -3,6 +3,8 @@
#include "entity.cpp"
#include "types.cpp"
String get_final_microarchitecture();
gb_internal void check_expr(CheckerContext *c, Operand *operand, Ast *expression);
gb_internal void check_expr_or_type(CheckerContext *c, Operand *operand, Ast *expression, Type *type_hint=nullptr);
gb_internal void add_comparison_procedures_for_fields(CheckerContext *c, Type *t);
@@ -1040,6 +1042,8 @@ gb_internal void init_universal(void) {
add_global_enum_constant(fields, "ODIN_ARCH", bc->metrics.arch);
add_global_string_constant("ODIN_ARCH_STRING", target_arch_names[bc->metrics.arch]);
}
add_global_string_constant("ODIN_MICROARCH_STRING", get_final_microarchitecture());
{
GlobalEnumValue values[BuildMode_COUNT] = {
@@ -1130,6 +1134,17 @@ gb_internal void init_universal(void) {
add_global_constant("ODIN_COMPILE_TIMESTAMP", t_untyped_integer, exact_value_i64(odin_compile_timestamp()));
{
String version = {};
#ifdef GIT_SHA
version.text = cast(u8 *)GIT_SHA;
version.len = gb_strlen(GIT_SHA);
#endif
add_global_string_constant("ODIN_VERSION_HASH", version);
}
{
bool f16_supported = lb_use_new_pass_system();
if (is_arch_wasm()) {
@@ -1167,6 +1182,18 @@ gb_internal void init_universal(void) {
add_global_constant("ODIN_SANITIZER_FLAGS", named_type, exact_value_u64(bc->sanitizer_flags));
}
{
GlobalEnumValue values[5] = {
{"None", -1},
{"Minimal", 0},
{"Size", 1},
{"Speed", 2},
{"Aggressive", 3},
};
auto fields = add_global_enum_type(str_lit("Odin_Optimization_Mode"), values, gb_count_of(values));
add_global_enum_constant(fields, "ODIN_OPTIMIZATION_MODE", bc->optimization_level);
}
// Builtin Procedures
@@ -1452,6 +1479,10 @@ gb_internal Entity *entity_of_node(Ast *expr) {
case_ast_node(cc, CaseClause, expr);
return cc->implicit_entity;
case_end;
case_ast_node(ce, CallExpr, expr);
return ce->entity_procedure_of;
case_end;
}
return nullptr;
}
+6
View File
@@ -51,6 +51,12 @@ enum StmtFlag {
enum BuiltinProcPkg {
BuiltinProcPkg_builtin,
BuiltinProcPkg_intrinsics,
BuiltinProcPkg_COUNT
};
String builtin_proc_pkg_name[BuiltinProcPkg_COUNT] = {
str_lit("builtin"),
str_lit("intrinsics"),
};
struct BuiltinProc {
+4
View File
@@ -299,6 +299,8 @@ BuiltinProc__type_simple_boolean_end,
BuiltinProc__type_end,
BuiltinProc_procedure_of,
BuiltinProc___entry_point,
BuiltinProc_objc_send,
@@ -614,6 +616,8 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = {
{STR_LIT(""), 0, false, Expr_Stmt, BuiltinProcPkg_intrinsics},
{STR_LIT("procedure_of"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
{STR_LIT("__entry_point"), 0, false, Expr_Stmt, BuiltinProcPkg_intrinsics},
{STR_LIT("objc_send"), 3, true, Expr_Expr, BuiltinProcPkg_intrinsics, false, true},
+1
View File
@@ -256,6 +256,7 @@ struct Entity {
bool generated_from_polymorphic : 1;
bool entry_point_only : 1;
bool has_instrumentation : 1;
bool is_memcpy_like : 1;
} Procedure;
struct {
Array<Entity *> entities;
+2 -2
View File
@@ -516,7 +516,7 @@ gb_internal void syntax_error_with_verbose_va(TokenPos const &pos, TokenPos end,
if (pos.line == 0) {
error_out_empty();
error_out_coloured("Syntax_Error: ", TerminalStyle_Normal, TerminalColour_Red);
error_out_coloured("Syntax Error: ", TerminalStyle_Normal, TerminalColour_Red);
error_out_va(fmt, va);
error_out("\n");
} else {
@@ -527,7 +527,7 @@ gb_internal void syntax_error_with_verbose_va(TokenPos const &pos, TokenPos end,
error_out_pos(pos);
}
if (has_ansi_terminal_colours()) {
error_out_coloured("Syntax_Error: ", TerminalStyle_Normal, TerminalColour_Red);
error_out_coloured("Syntax Error: ", TerminalStyle_Normal, TerminalColour_Red);
}
error_out_va(fmt, va);
error_out("\n");
+136 -108
View File
@@ -9,6 +9,11 @@
#endif
#ifndef LLVM_IGNORE_VERIFICATION
#define LLVM_IGNORE_VERIFICATION 0
#endif
#include "llvm_backend.hpp"
#include "llvm_abi.cpp"
#include "llvm_backend_opt.cpp"
@@ -1125,6 +1130,53 @@ gb_internal void lb_finalize_objc_names(lbProcedure *p) {
lb_end_procedure_body(p);
}
gb_internal void lb_verify_function(lbModule *m, lbProcedure *p, bool dump_ll=false) {
if (LLVM_IGNORE_VERIFICATION) {
return;
}
if (!m->debug_builder && LLVMVerifyFunction(p->value, LLVMReturnStatusAction)) {
char *llvm_error = nullptr;
gb_printf_err("LLVM CODE GEN FAILED FOR PROCEDURE: %.*s\n", LIT(p->name));
LLVMDumpValue(p->value);
gb_printf_err("\n");
if (dump_ll) {
gb_printf_err("\n\n\n");
String filepath_ll = lb_filepath_ll_for_module(m);
if (LLVMPrintModuleToFile(m->mod, cast(char const *)filepath_ll.text, &llvm_error)) {
gb_printf_err("LLVM Error: %s\n", llvm_error);
}
}
LLVMVerifyFunction(p->value, LLVMPrintMessageAction);
exit_with_errors();
}
}
gb_internal WORKER_TASK_PROC(lb_llvm_module_verification_worker_proc) {
char *llvm_error = nullptr;
defer (LLVMDisposeMessage(llvm_error));
lbModule *m = cast(lbModule *)data;
if (LLVMVerifyModule(m->mod, LLVMReturnStatusAction, &llvm_error)) {
gb_printf_err("LLVM Error:\n%s\n", llvm_error);
if (build_context.keep_temp_files) {
TIME_SECTION("LLVM Print Module to File");
String filepath_ll = lb_filepath_ll_for_module(m);
if (LLVMPrintModuleToFile(m->mod, cast(char const *)filepath_ll.text, &llvm_error)) {
gb_printf_err("LLVM Error: %s\n", llvm_error);
exit_with_errors();
return false;
}
}
exit_with_errors();
return 1;
}
return 0;
}
gb_internal lbProcedure *lb_create_startup_runtime(lbModule *main_module, lbProcedure *objc_names, Array<lbGlobalVariable> &global_variables) { // Startup Runtime
Type *proc_type = alloc_type_proc(nullptr, nullptr, 0, nullptr, 0, false, ProcCC_Odin);
@@ -1227,13 +1279,7 @@ gb_internal lbProcedure *lb_create_startup_runtime(lbModule *main_module, lbProc
lb_end_procedure_body(p);
if (!main_module->debug_builder && LLVMVerifyFunction(p->value, LLVMReturnStatusAction)) {
gb_printf_err("LLVM CODE GEN FAILED FOR PROCEDURE: %s\n", "main");
LLVMDumpValue(p->value);
gb_printf_err("\n\n\n\n");
LLVMVerifyFunction(p->value, LLVMAbortProcessAction);
}
lb_verify_function(main_module, p);
return p;
}
@@ -1256,31 +1302,21 @@ gb_internal lbProcedure *lb_create_cleanup_runtime(lbModule *main_module) { // C
lb_end_procedure_body(p);
if (!main_module->debug_builder && LLVMVerifyFunction(p->value, LLVMReturnStatusAction)) {
gb_printf_err("LLVM CODE GEN FAILED FOR PROCEDURE: %s\n", "main");
LLVMDumpValue(p->value);
gb_printf_err("\n\n\n\n");
LLVMVerifyFunction(p->value, LLVMAbortProcessAction);
}
lb_verify_function(main_module, p);
return p;
}
gb_internal WORKER_TASK_PROC(lb_generate_procedures_and_types_per_module) {
lbModule *m = cast(lbModule *)data;
for (Entity *e : m->global_procedures_and_types_to_create) {
if (e->kind == Entity_TypeName) {
(void)lb_get_entity_name(m, e);
lb_type(m, e->type);
}
for (Entity *e : m->global_types_to_create) {
(void)lb_get_entity_name(m, e);
(void)lb_type(m, e->type);
}
for (Entity *e : m->global_procedures_and_types_to_create) {
if (e->kind == Entity_Procedure) {
(void)lb_get_entity_name(m, e);
array_add(&m->procedures_to_generate, lb_create_procedure(m, e));
}
for (Entity *e : m->global_procedures_to_create) {
(void)lb_get_entity_name(m, e);
array_add(&m->procedures_to_generate, lb_create_procedure(m, e));
}
return 0;
}
@@ -1334,16 +1370,24 @@ gb_internal void lb_create_global_procedures_and_types(lbGenerator *gen, Checker
m = lb_module_of_entity(gen, e);
}
array_add(&m->global_procedures_and_types_to_create, e);
if (e->kind == Entity_Procedure) {
array_add(&m->global_procedures_to_create, e);
} else if (e->kind == Entity_TypeName) {
array_add(&m->global_types_to_create, e);
}
}
for (auto const &entry : gen->modules) {
lbModule *m = entry.value;
if (do_threading) {
if (do_threading) {
for (auto const &entry : gen->modules) {
lbModule *m = entry.value;
thread_pool_add_task(lb_generate_procedures_and_types_per_module, m);
} else {
}
} else {
for (auto const &entry : gen->modules) {
lbModule *m = entry.value;
lb_generate_procedures_and_types_per_module(m);
}
}
thread_pool_wait();
@@ -2374,16 +2418,19 @@ gb_internal WORKER_TASK_PROC(lb_generate_procedures_worker_proc) {
}
gb_internal void lb_generate_procedures(lbGenerator *gen, bool do_threading) {
for (auto const &entry : gen->modules) {
lbModule *m = entry.value;
if (do_threading) {
if (do_threading) {
for (auto const &entry : gen->modules) {
lbModule *m = entry.value;
thread_pool_add_task(lb_generate_procedures_worker_proc, m);
} else {
}
thread_pool_wait();
} else {
for (auto const &entry : gen->modules) {
lbModule *m = entry.value;
lb_generate_procedures_worker_proc(m);
}
}
thread_pool_wait();
}
gb_internal WORKER_TASK_PROC(lb_generate_missing_procedures_to_check_worker_proc) {
@@ -2397,17 +2444,20 @@ gb_internal WORKER_TASK_PROC(lb_generate_missing_procedures_to_check_worker_proc
}
gb_internal void lb_generate_missing_procedures(lbGenerator *gen, bool do_threading) {
for (auto const &entry : gen->modules) {
lbModule *m = entry.value;
// NOTE(bill): procedures may be added during generation
if (do_threading) {
if (do_threading) {
for (auto const &entry : gen->modules) {
lbModule *m = entry.value;
// NOTE(bill): procedures may be added during generation
thread_pool_add_task(lb_generate_missing_procedures_to_check_worker_proc, m);
} else {
}
thread_pool_wait();
} else {
for (auto const &entry : gen->modules) {
lbModule *m = entry.value;
// NOTE(bill): procedures may be added during generation
lb_generate_missing_procedures_to_check_worker_proc(m);
}
}
thread_pool_wait();
}
gb_internal void lb_debug_info_complete_types_and_finalize(lbGenerator *gen) {
@@ -2420,32 +2470,45 @@ gb_internal void lb_debug_info_complete_types_and_finalize(lbGenerator *gen) {
}
gb_internal void lb_llvm_function_passes(lbGenerator *gen, bool do_threading) {
for (auto const &entry : gen->modules) {
lbModule *m = entry.value;
if (do_threading) {
if (do_threading) {
for (auto const &entry : gen->modules) {
lbModule *m = entry.value;
thread_pool_add_task(lb_llvm_function_pass_per_module, m);
} else {
}
thread_pool_wait();
} else {
for (auto const &entry : gen->modules) {
lbModule *m = entry.value;
lb_llvm_function_pass_per_module(m);
}
}
thread_pool_wait();
}
gb_internal void lb_llvm_module_passes(lbGenerator *gen, bool do_threading) {
for (auto const &entry : gen->modules) {
lbModule *m = entry.value;
auto wd = gb_alloc_item(permanent_allocator(), lbLLVMModulePassWorkerData);
wd->m = m;
wd->target_machine = m->target_machine;
if (do_threading) {
for (auto const &entry : gen->modules) {
lbModule *m = entry.value;
auto wd = gb_alloc_item(permanent_allocator(), lbLLVMModulePassWorkerData);
wd->m = m;
wd->target_machine = m->target_machine;
if (do_threading) {
thread_pool_add_task(lb_llvm_module_pass_worker_proc, wd);
} else {
if (do_threading) {
thread_pool_add_task(lb_llvm_module_pass_worker_proc, wd);
} else {
lb_llvm_module_pass_worker_proc(wd);
}
}
thread_pool_wait();
} else {
for (auto const &entry : gen->modules) {
lbModule *m = entry.value;
auto wd = gb_alloc_item(permanent_allocator(), lbLLVMModulePassWorkerData);
wd->m = m;
wd->target_machine = m->target_machine;
lb_llvm_module_pass_worker_proc(wd);
}
}
thread_pool_wait();
}
gb_internal String lb_filepath_ll_for_module(lbModule *m) {
@@ -2523,40 +2586,27 @@ gb_internal String lb_filepath_obj_for_module(lbModule *m) {
return concatenate_strings(permanent_allocator(), path, ext);
}
gb_internal WORKER_TASK_PROC(lb_llvm_module_verification_worker_proc) {
char *llvm_error = nullptr;
defer (LLVMDisposeMessage(llvm_error));
lbModule *m = cast(lbModule *)data;
if (LLVMVerifyModule(m->mod, LLVMReturnStatusAction, &llvm_error)) {
gb_printf_err("LLVM Error:\n%s\n", llvm_error);
if (build_context.keep_temp_files) {
TIME_SECTION("LLVM Print Module to File");
String filepath_ll = lb_filepath_ll_for_module(m);
if (LLVMPrintModuleToFile(m->mod, cast(char const *)filepath_ll.text, &llvm_error)) {
gb_printf_err("LLVM Error: %s\n", llvm_error);
exit_with_errors();
return false;
}
}
exit_with_errors();
return 1;
}
return 0;
}
gb_internal bool lb_llvm_module_verification(lbGenerator *gen, bool do_threading) {
for (auto const &entry : gen->modules) {
lbModule *m = entry.value;
if (do_threading) {
if (LLVM_IGNORE_VERIFICATION) {
return true;
}
if (do_threading) {
for (auto const &entry : gen->modules) {
lbModule *m = entry.value;
thread_pool_add_task(lb_llvm_module_verification_worker_proc, m);
} else {
}
thread_pool_wait();
} else {
for (auto const &entry : gen->modules) {
lbModule *m = entry.value;
if (lb_llvm_module_verification_worker_proc(m)) {
return false;
}
}
}
thread_pool_wait();
return true;
}
@@ -2777,12 +2827,7 @@ gb_internal lbProcedure *lb_create_main_procedure(lbModule *m, lbProcedure *star
}
if (!m->debug_builder && LLVMVerifyFunction(p->value, LLVMReturnStatusAction)) {
gb_printf_err("LLVM CODE GEN FAILED FOR PROCEDURE: %s\n", "main");
LLVMDumpValue(p->value);
gb_printf_err("\n\n\n\n");
LLVMVerifyFunction(p->value, LLVMAbortProcessAction);
}
lb_verify_function(m, p);
lb_run_function_pass_manager(default_function_pass_manager, p, lbFunctionPassManager_default);
return p;
@@ -2803,28 +2848,11 @@ gb_internal void lb_generate_procedure(lbModule *m, lbProcedure *p) {
lb_end_procedure(p);
// Add Flags
if (p->body != nullptr) {
if (p->name == "memcpy" || p->name == "memmove" ||
p->name == "runtime.mem_copy" || p->name == "mem_copy_non_overlapping" ||
string_starts_with(p->name, str_lit("llvm.memcpy")) ||
string_starts_with(p->name, str_lit("llvm.memmove"))) {
p->flags |= lbProcedureFlag_WithoutMemcpyPass;
}
if (p->entity && p->entity->kind == Entity_Procedure && p->entity->Procedure.is_memcpy_like) {
p->flags |= lbProcedureFlag_WithoutMemcpyPass;
}
if (!m->debug_builder && LLVMVerifyFunction(p->value, LLVMReturnStatusAction)) {
char *llvm_error = nullptr;
gb_printf_err("LLVM CODE GEN FAILED FOR PROCEDURE: %.*s\n", LIT(p->name));
LLVMDumpValue(p->value);
gb_printf_err("\n\n\n\n");
String filepath_ll = lb_filepath_ll_for_module(m);
if (LLVMPrintModuleToFile(m->mod, cast(char const *)filepath_ll.text, &llvm_error)) {
gb_printf_err("LLVM Error: %s\n", llvm_error);
}
LLVMVerifyFunction(p->value, LLVMPrintMessageAction);
exit_with_errors();
}
lb_verify_function(m, p, true);
}
+2 -1
View File
@@ -181,7 +181,8 @@ struct lbModule {
std::atomic<u32> nested_type_name_guid;
Array<lbProcedure *> procedures_to_generate;
Array<Entity *> global_procedures_and_types_to_create;
Array<Entity *> global_procedures_to_create;
Array<Entity *> global_types_to_create;
lbProcedure *curr_procedure;
+18 -18
View File
@@ -626,50 +626,50 @@ gb_internal LLVMMetadataRef lb_debug_type_internal(lbModule *m, Type *type) {
case Basic_complex32:
{
LLVMMetadataRef elements[2] = {};
elements[0] = lb_debug_struct_field(m, str_lit("real"), t_f16, 0);
elements[1] = lb_debug_struct_field(m, str_lit("imag"), t_f16, 4);
elements[0] = lb_debug_struct_field(m, str_lit("real"), t_f16, 0*16);
elements[1] = lb_debug_struct_field(m, str_lit("imag"), t_f16, 1*16);
return lb_debug_basic_struct(m, str_lit("complex32"), 64, 32, elements, gb_count_of(elements));
}
case Basic_complex64:
{
LLVMMetadataRef elements[2] = {};
elements[0] = lb_debug_struct_field(m, str_lit("real"), t_f32, 0);
elements[1] = lb_debug_struct_field(m, str_lit("imag"), t_f32, 4);
elements[0] = lb_debug_struct_field(m, str_lit("real"), t_f32, 0*32);
elements[1] = lb_debug_struct_field(m, str_lit("imag"), t_f32, 2*32);
return lb_debug_basic_struct(m, str_lit("complex64"), 64, 32, elements, gb_count_of(elements));
}
case Basic_complex128:
{
LLVMMetadataRef elements[2] = {};
elements[0] = lb_debug_struct_field(m, str_lit("real"), t_f64, 0);
elements[1] = lb_debug_struct_field(m, str_lit("imag"), t_f64, 8);
elements[0] = lb_debug_struct_field(m, str_lit("real"), t_f64, 0*64);
elements[1] = lb_debug_struct_field(m, str_lit("imag"), t_f64, 1*64);
return lb_debug_basic_struct(m, str_lit("complex128"), 128, 64, elements, gb_count_of(elements));
}
case Basic_quaternion64:
{
LLVMMetadataRef elements[4] = {};
elements[0] = lb_debug_struct_field(m, str_lit("imag"), t_f16, 0);
elements[1] = lb_debug_struct_field(m, str_lit("jmag"), t_f16, 4);
elements[2] = lb_debug_struct_field(m, str_lit("kmag"), t_f16, 8);
elements[3] = lb_debug_struct_field(m, str_lit("real"), t_f16, 12);
elements[0] = lb_debug_struct_field(m, str_lit("imag"), t_f16, 0*16);
elements[1] = lb_debug_struct_field(m, str_lit("jmag"), t_f16, 1*16);
elements[2] = lb_debug_struct_field(m, str_lit("kmag"), t_f16, 2*16);
elements[3] = lb_debug_struct_field(m, str_lit("real"), t_f16, 3*16);
return lb_debug_basic_struct(m, str_lit("quaternion64"), 128, 32, elements, gb_count_of(elements));
}
case Basic_quaternion128:
{
LLVMMetadataRef elements[4] = {};
elements[0] = lb_debug_struct_field(m, str_lit("imag"), t_f32, 0);
elements[1] = lb_debug_struct_field(m, str_lit("jmag"), t_f32, 4);
elements[2] = lb_debug_struct_field(m, str_lit("kmag"), t_f32, 8);
elements[3] = lb_debug_struct_field(m, str_lit("real"), t_f32, 12);
elements[0] = lb_debug_struct_field(m, str_lit("imag"), t_f32, 0*32);
elements[1] = lb_debug_struct_field(m, str_lit("jmag"), t_f32, 1*32);
elements[2] = lb_debug_struct_field(m, str_lit("kmag"), t_f32, 2*32);
elements[3] = lb_debug_struct_field(m, str_lit("real"), t_f32, 3*32);
return lb_debug_basic_struct(m, str_lit("quaternion128"), 128, 32, elements, gb_count_of(elements));
}
case Basic_quaternion256:
{
LLVMMetadataRef elements[4] = {};
elements[0] = lb_debug_struct_field(m, str_lit("imag"), t_f64, 0);
elements[1] = lb_debug_struct_field(m, str_lit("jmag"), t_f64, 8);
elements[2] = lb_debug_struct_field(m, str_lit("kmag"), t_f64, 16);
elements[3] = lb_debug_struct_field(m, str_lit("real"), t_f64, 24);
elements[0] = lb_debug_struct_field(m, str_lit("imag"), t_f64, 0*64);
elements[1] = lb_debug_struct_field(m, str_lit("jmag"), t_f64, 1*64);
elements[2] = lb_debug_struct_field(m, str_lit("kmag"), t_f64, 2*64);
elements[3] = lb_debug_struct_field(m, str_lit("real"), t_f64, 3*64);
return lb_debug_basic_struct(m, str_lit("quaternion256"), 256, 32, elements, gb_count_of(elements));
}
+2 -1
View File
@@ -78,7 +78,8 @@ gb_internal void lb_init_module(lbModule *m, Checker *c) {
array_init(&m->procedures_to_generate, a, 0, c->info.all_procedures.count);
map_init(&m->procedure_values, c->info.all_procedures.count*2);
}
array_init(&m->global_procedures_and_types_to_create, a, 0, 1024);
array_init(&m->global_procedures_to_create, a, 0, 1024);
array_init(&m->global_types_to_create, a, 0, 1024);
array_init(&m->missing_procedures_to_check, a, 0, 16);
map_init(&m->debug_values);
+11 -6
View File
@@ -555,7 +555,7 @@ gb_internal Ast *ast_unary_expr(AstFile *f, Token op, Ast *expr) {
syntax_error_with_verbose(expr, "'or_return' within an unary expression not wrapped in parentheses (...)");
break;
case Ast_OrBranchExpr:
syntax_error_with_verbose(expr, "'or_%.*s' within an unary expression not wrapped in parentheses (...)", LIT(expr->OrBranchExpr.token.string));
syntax_error_with_verbose(expr, "'%.*s' within an unary expression not wrapped in parentheses (...)", LIT(expr->OrBranchExpr.token.string));
break;
}
@@ -583,7 +583,7 @@ gb_internal Ast *ast_binary_expr(AstFile *f, Token op, Ast *left, Ast *right) {
syntax_error_with_verbose(left, "'or_return' within a binary expression not wrapped in parentheses (...)");
break;
case Ast_OrBranchExpr:
syntax_error_with_verbose(left, "'or_%.*s' within a binary expression not wrapped in parentheses (...)", LIT(left->OrBranchExpr.token.string));
syntax_error_with_verbose(left, "'%.*s' within a binary expression not wrapped in parentheses (...)", LIT(left->OrBranchExpr.token.string));
break;
}
if (right) switch (right->kind) {
@@ -591,7 +591,7 @@ gb_internal Ast *ast_binary_expr(AstFile *f, Token op, Ast *left, Ast *right) {
syntax_error_with_verbose(right, "'or_return' within a binary expression not wrapped in parentheses (...)");
break;
case Ast_OrBranchExpr:
syntax_error_with_verbose(right, "'or_%.*s' within a binary expression not wrapped in parentheses (...)", LIT(right->OrBranchExpr.token.string));
syntax_error_with_verbose(right, "'%.*s' within a binary expression not wrapped in parentheses (...)", LIT(right->OrBranchExpr.token.string));
break;
}
@@ -2091,6 +2091,9 @@ gb_internal bool ast_on_same_line(Token const &x, Ast *yp) {
gb_internal Ast *parse_force_inlining_operand(AstFile *f, Token token) {
Ast *expr = parse_unary_expr(f, false);
Ast *e = strip_or_return_expr(expr);
if (e == nullptr) {
return expr;
}
if (e->kind != Ast_ProcLit && e->kind != Ast_CallExpr) {
syntax_error(expr, "%.*s must be followed by a procedure literal or call, got %.*s", LIT(token.string), LIT(ast_strings[expr->kind]));
return ast_bad_expr(f, token, f->curr_token);
@@ -3102,7 +3105,7 @@ gb_internal void parse_check_or_return(Ast *operand, char const *msg) {
syntax_error_with_verbose(operand, "'or_return' use within %s is not wrapped in parentheses (...)", msg);
break;
case Ast_OrBranchExpr:
syntax_error_with_verbose(operand, "'or_%.*s' use within %s is not wrapped in parentheses (...)", msg, LIT(operand->OrBranchExpr.token.string));
syntax_error_with_verbose(operand, "'%.*s' use within %s is not wrapped in parentheses (...)", msg, LIT(operand->OrBranchExpr.token.string));
break;
}
}
@@ -3747,8 +3750,10 @@ gb_internal Ast *parse_simple_stmt(AstFile *f, u32 flags) {
case Ast_TypeSwitchStmt:
stmt->TypeSwitchStmt.partial = true;
break;
default:
syntax_error(partial_token, "Incorrect use of directive, use '%.*s: #partial switch'", LIT(ast_token(name).string));
break;
}
syntax_error(partial_token, "Incorrect use of directive, use '#partial %.*s: switch'", LIT(ast_token(name).string));
} else if (is_reverse) {
switch (stmt->kind) {
case Ast_RangeStmt:
@@ -5176,7 +5181,7 @@ gb_internal Ast *parse_stmt(AstFile *f) {
} else if (tag == "unroll") {
return parse_unrolled_for_loop(f, name);
} else if (tag == "reverse") {
Ast *for_stmt = parse_for_stmt(f);
Ast *for_stmt = parse_stmt(f);
if (for_stmt->kind == Ast_RangeStmt) {
if (for_stmt->RangeStmt.reverse) {
syntax_error(token, "#reverse already applied to a 'for in' statement");
+1
View File
@@ -458,6 +458,7 @@ AST_KIND(_ExprBegin, "", bool) \
bool optional_ok_one; \
bool was_selector; \
AstSplitArgs *split_args; \
Entity *entity_procedure_of; \
}) \
AST_KIND(FieldValue, "field value", struct { Token eq; Ast *field, *value; }) \
AST_KIND(EnumFieldValue, "enum field value", struct { \