Merge branch 'master' into windows-llvm-13.0.0

This commit is contained in:
gingerBill
2023-03-16 12:45:06 +00:00
33 changed files with 451 additions and 136 deletions

View File

@@ -275,6 +275,7 @@ struct BuildContext {
bool no_output_files;
bool no_crt;
bool no_entry_point;
bool no_thread_local;
bool use_lld;
bool vet;
bool vet_extra;
@@ -1255,7 +1256,7 @@ gb_internal void init_build_context(TargetMetrics *cross_target) {
gb_exit(1);
}
bc->optimization_level = gb_clamp(bc->optimization_level, 0, 3);
bc->optimization_level = gb_clamp(bc->optimization_level, -1, 2);
// ENFORCE DYNAMIC MAP CALLS
bc->dynamic_map_calls = true;
@@ -1369,6 +1370,7 @@ gb_internal char const *target_features_set_to_cstring(gbAllocator allocator, bo
gb_memmove(features + len, feature.text, feature.len);
len += feature.len;
if (with_quotes) features[len++] = '"';
i += 1;
}
features[len++] = 0;

View File

@@ -1143,9 +1143,12 @@ gb_internal void check_global_variable_decl(CheckerContext *ctx, Entity *&e, Ast
if (is_arch_wasm() && e->Variable.thread_local_model.len != 0) {
e->Variable.thread_local_model.len = 0;
// NOTE(bill): ignore this message for the time begin
// NOTE(bill): ignore this message for the time being
// error(e->token, "@(thread_local) is not supported for this target platform");
}
if(build_context.no_thread_local) {
e->Variable.thread_local_model.len = 0;
}
String context_name = str_lit("variable declaration");

View File

@@ -1184,6 +1184,8 @@ gb_internal void check_type_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_
return;
}
Ast *nil_seen = nullptr;
PtrSet<Type *> seen = {};
defer (ptr_set_destroy(&seen));
@@ -1194,6 +1196,7 @@ gb_internal void check_type_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_
}
ast_node(cc, CaseClause, stmt);
bool saw_nil = false;
// TODO(bill): Make robust
Type *bt = base_type(type_deref(x.type));
@@ -1202,6 +1205,25 @@ gb_internal void check_type_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_
if (type_expr != nullptr) { // Otherwise it's a default expression
Operand y = {};
check_expr_or_type(ctx, &y, type_expr);
if (is_operand_nil(y)) {
if (!type_has_nil(type_deref(x.type))) {
error(type_expr, "'nil' case is not allowed for the type '%s'", type_to_string(type_deref(x.type)));
continue;
}
saw_nil = true;
if (nil_seen) {
ERROR_BLOCK();
error(type_expr, "'nil' case has already been handled previously");
error_line("\t 'nil' was already previously seen at %s", token_pos_to_string(ast_token(nil_seen).pos));
} else {
nil_seen = type_expr;
}
case_type = y.type;
continue;
}
if (y.mode != Addressing_Type) {
gbString str = expr_to_string(type_expr);
error(type_expr, "Expected a type as a case, got %s", str);
@@ -1255,14 +1277,16 @@ gb_internal void check_type_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_
is_reference = true;
}
if (cc->list.count > 1) {
if (cc->list.count > 1 || saw_nil) {
case_type = nullptr;
}
if (case_type == nullptr) {
case_type = x.type;
}
if (switch_kind == TypeSwitch_Any) {
add_type_info_type(ctx, case_type);
if (!is_type_untyped(case_type)) {
add_type_info_type(ctx, case_type);
}
}
check_open_scope(ctx, stmt);

View File

@@ -674,6 +674,10 @@ gb_internal void check_union_type(CheckerContext *ctx, Type *union_type, Ast *no
for_array(i, ut->variants) {
Ast *node = ut->variants[i];
Type *t = check_type_expr(ctx, node, nullptr);
if (union_type->Union.is_polymorphic && poly_operands == nullptr) {
// NOTE(bill): don't add any variants if this is this is an unspecialized polymorphic record
continue;
}
if (t != nullptr && t != t_invalid) {
bool ok = true;
t = default_type(t);
@@ -686,8 +690,12 @@ gb_internal void check_union_type(CheckerContext *ctx, Type *union_type, Ast *no
for_array(j, variants) {
if (are_types_identical(t, variants[j])) {
ok = false;
ERROR_BLOCK();
gbString str = type_to_string(t);
error(node, "Duplicate variant type '%s'", str);
if (j < ut->variants.count) {
error_line("\tPrevious found at %s\n", token_pos_to_string(ast_token(ut->variants[j]).pos));
}
gb_string_free(str);
break;
}

View File

@@ -1,4 +1,5 @@
#include <math.h>
#include <stdlib.h>
gb_global BlockingMutex hash_exact_value_mutex;
@@ -174,7 +175,36 @@ gb_internal ExactValue exact_value_integer_from_string(String const &string) {
gb_internal f64 float_from_string(String string) {
gb_internal f64 float_from_string(String const &string) {
if (string.len < 128) {
char buf[128] = {};
isize n = 0;
for (isize i = 0; i < string.len; i++) {
u8 c = string.text[i];
if (c == '_') {
continue;
}
if (c == 'E') { c = 'e'; }
buf[n++] = cast(char)c;
}
buf[n] = 0;
return atof(buf);
} else {
TEMPORARY_ALLOCATOR_GUARD();
char *buf = gb_alloc_array(temporary_allocator(), char, string.len+1);
isize n = 0;
for (isize i = 0; i < string.len; i++) {
u8 c = string.text[i];
if (c == '_') {
continue;
}
if (c == 'E') { c = 'e'; }
buf[n++] = cast(char)c;
}
buf[n] = 0;
return atof(buf);
}
/*
isize i = 0;
u8 *str = string.text;
isize len = string.len;
@@ -250,6 +280,7 @@ gb_internal f64 float_from_string(String string) {
}
return sign * (frac ? (value / scale) : (value * scale));
*/
}
gb_internal ExactValue exact_value_float_from_string(String string) {

View File

@@ -337,6 +337,8 @@ struct lbProcedure {
LLVMMetadataRef debug_info;
lbAddr current_elision_hint;
PtrMap<Ast *, lbValue> selector_values;
PtrMap<Ast *, lbAddr> selector_addr;
PtrMap<LLVMValueRef, lbTupleFix> tuple_fix_map;

View File

@@ -484,7 +484,14 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bo
LLVMValueRef indices[2] = {llvm_zero(m), llvm_zero(m)};
LLVMValueRef ptr = LLVMBuildInBoundsGEP2(p->builder, llvm_type, array_data, indices, 2, "");
LLVMValueRef len = LLVMConstInt(lb_type(m, t_int), count, true);
lbAddr slice = lb_add_local_generated(p, type, false);
lbAddr slice = {};
if (p->current_elision_hint.addr.value && are_types_identical(lb_addr_type(p->current_elision_hint), type)) {
slice = p->current_elision_hint;
p->current_elision_hint = {};
} else {
slice = lb_add_local_generated(p, type, false);
}
map_set(&m->exact_value_compound_literal_addr_map, value.value_compound, slice);
lb_fill_slice(p, slice, {ptr, alloc_type_pointer(elem)}, {len, t_int});

View File

@@ -989,7 +989,6 @@ gb_internal void lb_add_debug_local_variable(lbProcedure *p, LLVMValueRef ptr, T
return;
}
AstFile *file = p->body->file();
LLVMMetadataRef llvm_scope = lb_get_current_debug_scope(p);

View File

@@ -63,7 +63,6 @@ gb_internal void lb_init_module(lbModule *m, Checker *c) {
map_init(&m->values);
map_init(&m->soa_values);
string_map_init(&m->members);
map_init(&m->procedure_values);
string_map_init(&m->procedures);
string_map_init(&m->const_strings);
map_init(&m->function_type_map);
@@ -71,7 +70,13 @@ gb_internal void lb_init_module(lbModule *m, Checker *c) {
map_init(&m->hasher_procs);
map_init(&m->map_get_procs);
map_init(&m->map_set_procs);
array_init(&m->procedures_to_generate, a, 0, 1024);
if (build_context.use_separate_modules) {
array_init(&m->procedures_to_generate, a, 0, 1<<10);
map_init(&m->procedure_values, 1<<11);
} else {
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->missing_procedures_to_check, a, 0, 16);
map_init(&m->debug_values);

View File

@@ -55,8 +55,17 @@ gb_internal void lb_populate_function_pass_manager_specific(lbModule *m, LLVMPas
#define LLVM_ADD_CONSTANT_VALUE_PASS(fpm)
#endif
gb_internal bool lb_opt_ignore(i32 optimization_level) {
optimization_level = gb_clamp(optimization_level, -1, 2);
return optimization_level == -1;
}
gb_internal void lb_basic_populate_function_pass_manager(LLVMPassManagerRef fpm, i32 optimization_level) {
if (false && optimization_level == 0 && build_context.ODIN_DEBUG) {
if (lb_opt_ignore(optimization_level)) {
return;
}
if (false && optimization_level <= 0 && build_context.ODIN_DEBUG) {
LLVMAddMergedLoadStoreMotionPass(fpm);
} else {
LLVMAddPromoteMemoryToRegisterPass(fpm);
@@ -69,14 +78,14 @@ gb_internal void lb_basic_populate_function_pass_manager(LLVMPassManagerRef fpm,
}
gb_internal void lb_populate_function_pass_manager(lbModule *m, LLVMPassManagerRef fpm, bool ignore_memcpy_pass, i32 optimization_level) {
// NOTE(bill): Treat -opt:3 as if it was -opt:2
// TODO(bill): Determine which opt definitions should exist in the first place
optimization_level = gb_clamp(optimization_level, 0, 2);
if (lb_opt_ignore(optimization_level)) {
return;
}
if (ignore_memcpy_pass) {
lb_basic_populate_function_pass_manager(fpm, optimization_level);
return;
} else if (optimization_level == 0) {
} else if (optimization_level <= 0) {
LLVMAddMemCpyOptPass(fpm);
lb_basic_populate_function_pass_manager(fpm, optimization_level);
return;
@@ -103,11 +112,11 @@ gb_internal void lb_populate_function_pass_manager(lbModule *m, LLVMPassManagerR
}
gb_internal void lb_populate_function_pass_manager_specific(lbModule *m, LLVMPassManagerRef fpm, i32 optimization_level) {
// NOTE(bill): Treat -opt:3 as if it was -opt:2
// TODO(bill): Determine which opt definitions should exist in the first place
optimization_level = gb_clamp(optimization_level, 0, 2);
if (lb_opt_ignore(optimization_level)) {
return;
}
if (optimization_level == 0) {
if (optimization_level <= 0) {
LLVMAddMemCpyOptPass(fpm);
lb_basic_populate_function_pass_manager(fpm, optimization_level);
return;
@@ -181,8 +190,7 @@ gb_internal void lb_populate_module_pass_manager(LLVMTargetMachineRef target_mac
// NOTE(bill): Treat -opt:3 as if it was -opt:2
// TODO(bill): Determine which opt definitions should exist in the first place
optimization_level = gb_clamp(optimization_level, 0, 2);
if (optimization_level == 0 && build_context.ODIN_DEBUG) {
if (optimization_level <= 0 && build_context.ODIN_DEBUG) {
return;
}
@@ -190,7 +198,7 @@ gb_internal void lb_populate_module_pass_manager(LLVMTargetMachineRef target_mac
LLVMAddStripDeadPrototypesPass(mpm);
LLVMAddAnalysisPasses(target_machine, mpm);
LLVMAddPruneEHPass(mpm);
if (optimization_level == 0) {
if (optimization_level <= 0) {
return;
}
@@ -267,6 +275,9 @@ gb_internal void lb_populate_module_pass_manager(LLVMTargetMachineRef target_mac
**************************************************************************/
gb_internal void lb_run_remove_dead_instruction_pass(lbProcedure *p) {
unsigned debug_declare_id = LLVMLookupIntrinsicID("llvm.dbg.declare", 16);
GB_ASSERT(debug_declare_id != 0);
isize removal_count = 0;
isize pass_count = 0;
isize const max_pass_count = 10;
@@ -302,6 +313,8 @@ gb_internal void lb_run_remove_dead_instruction_pass(lbProcedure *p) {
// NOTE(bill): Explicit instructions are set here because some instructions could have side effects
switch (LLVMGetInstructionOpcode(curr_instr)) {
// case LLVMAlloca:
case LLVMFNeg:
case LLVMAdd:
case LLVMFAdd:
@@ -321,7 +334,6 @@ gb_internal void lb_run_remove_dead_instruction_pass(lbProcedure *p) {
case LLVMAnd:
case LLVMOr:
case LLVMXor:
case LLVMAlloca:
case LLVMLoad:
case LLVMGetElementPtr:
case LLVMTrunc:

View File

@@ -791,15 +791,6 @@ gb_internal void lb_build_range_stmt(lbProcedure *p, AstRangeStmt *rs, Scope *sc
val1_type = type_of_expr(rs->vals[1]);
}
if (val0_type != nullptr) {
Entity *e = entity_of_node(rs->vals[0]);
lb_add_local(p, e->type, e, true);
}
if (val1_type != nullptr) {
Entity *e = entity_of_node(rs->vals[1]);
lb_add_local(p, e->type, e, true);
}
lbValue val = {};
lbValue key = {};
lbBlock *loop = nullptr;
@@ -1308,6 +1299,7 @@ gb_internal lbAddr lb_store_range_stmt_val(lbProcedure *p, Ast *stmt_val, lbValu
if (LLVMIsALoadInst(value.value)) {
lbValue ptr = lb_address_from_load_or_generate_local(p, value);
lb_add_entity(p->module, e, ptr);
lb_add_debug_local_variable(p, ptr.value, e->type, e->token);
return lb_addr(ptr);
}
}
@@ -1431,9 +1423,11 @@ gb_internal void lb_build_type_switch_stmt(lbProcedure *p, AstTypeSwitchStmt *ss
continue;
}
Entity *case_entity = implicit_entity_of_node(clause);
max_size = gb_max(max_size, type_size_of(case_entity->type));
max_align = gb_max(max_align, type_align_of(case_entity->type));
variants_found = true;
if (!is_type_untyped_nil(case_entity->type)) {
max_size = gb_max(max_size, type_size_of(case_entity->type));
max_align = gb_max(max_align, type_align_of(case_entity->type));
variants_found = true;
}
}
if (variants_found) {
Type *t = alloc_type_array(t_u8, max_size);
@@ -1457,6 +1451,8 @@ gb_internal void lb_build_type_switch_stmt(lbProcedure *p, AstTypeSwitchStmt *ss
if (p->debug_info != nullptr) {
LLVMSetCurrentDebugLocation2(p->builder, lb_debug_location_from_ast(p, clause));
}
bool saw_nil = false;
for (Ast *type_expr : cc->list) {
Type *case_type = type_of_expr(type_expr);
lbValue on_val = {};
@@ -1465,7 +1461,12 @@ gb_internal void lb_build_type_switch_stmt(lbProcedure *p, AstTypeSwitchStmt *ss
on_val = lb_const_union_tag(m, ut, case_type);
} else if (switch_kind == TypeSwitch_Any) {
on_val = lb_typeid(m, case_type);
if (is_type_untyped_nil(case_type)) {
saw_nil = true;
on_val = lb_const_nil(m, t_typeid);
} else {
on_val = lb_typeid(m, case_type);
}
}
GB_ASSERT(on_val.value != nullptr);
LLVMAddCase(switch_instr, on_val.value, body->block);
@@ -1477,7 +1478,7 @@ gb_internal void lb_build_type_switch_stmt(lbProcedure *p, AstTypeSwitchStmt *ss
bool by_reference = (case_entity->flags & EntityFlag_Value) == 0;
if (cc->list.count == 1) {
if (cc->list.count == 1 && !saw_nil) {
lbValue data = {};
if (switch_kind == TypeSwitch_Union) {
data = union_data;
@@ -2287,18 +2288,25 @@ gb_internal void lb_build_stmt(lbProcedure *p, Ast *node) {
isize lval_index = 0;
for (Ast *rhs : values) {
p->current_elision_hint = lvals[lval_index];
rhs = unparen_expr(rhs);
lbValue init = lb_build_expr(p, rhs);
#if 1
// NOTE(bill, 2023-02-17): lb_const_value might produce a stack local variable for the
// compound literal, so reusing that variable should minimize the stack wastage
if (rhs->kind == Ast_CompoundLit) {
lbAddr *comp_lit_addr = map_get(&p->module->exact_value_compound_literal_addr_map, rhs);
if (comp_lit_addr) {
Entity *e = entity_of_node(vd->names[lval_index]);
if (e) {
lb_add_entity(p->module, e, comp_lit_addr->addr);
lvals[lval_index] = {}; // do nothing so that nothing will assign to it
if (p->current_elision_hint.addr.value != lvals[lval_index].addr.value) {
lvals[lval_index] = {}; // do nothing so that nothing will assign to it
} else {
// NOTE(bill, 2023-02-17): lb_const_value might produce a stack local variable for the
// compound literal, so reusing that variable should minimize the stack wastage
if (rhs->kind == Ast_CompoundLit) {
lbAddr *comp_lit_addr = map_get(&p->module->exact_value_compound_literal_addr_map, rhs);
if (comp_lit_addr) {
Entity *e = entity_of_node(vd->names[lval_index]);
if (e) {
GB_ASSERT(p->current_elision_hint.addr.value == nullptr);
GB_ASSERT(p->current_elision_hint.addr.value != lvals[lval_index].addr.value);
lvals[lval_index] = {}; // do nothing so that nothing will assign to it
}
}
}
}
@@ -2308,6 +2316,8 @@ gb_internal void lb_build_stmt(lbProcedure *p, Ast *node) {
}
GB_ASSERT(lval_index == lvals.count);
p->current_elision_hint = {};
GB_ASSERT(lvals.count == inits.count);
for_array(i, inits) {
lbAddr lval = lvals[i];

View File

@@ -634,6 +634,7 @@ enum BuildFlagKind {
BuildFlag_Microarch,
BuildFlag_TargetFeatures,
BuildFlag_MinimumOSVersion,
BuildFlag_NoThreadLocal,
BuildFlag_RelocMode,
BuildFlag_DisableRedZone,
@@ -794,6 +795,7 @@ gb_internal bool parse_build_flags(Array<String> args) {
add_flag(&build_flags, BuildFlag_Debug, str_lit("debug"), BuildFlagParam_None, Command__does_check);
add_flag(&build_flags, BuildFlag_DisableAssert, str_lit("disable-assert"), BuildFlagParam_None, Command__does_check);
add_flag(&build_flags, BuildFlag_NoBoundsCheck, str_lit("no-bounds-check"), BuildFlagParam_None, Command__does_check);
add_flag(&build_flags, BuildFlag_NoThreadLocal, str_lit("no-thread-local"), BuildFlagParam_None, Command__does_check);
add_flag(&build_flags, BuildFlag_NoDynamicLiterals, str_lit("no-dynamic-literals"), BuildFlagParam_None, Command__does_check);
add_flag(&build_flags, BuildFlag_NoCRT, str_lit("no-crt"), BuildFlagParam_None, Command__does_build);
add_flag(&build_flags, BuildFlag_NoEntryPoint, str_lit("no-entry-point"), BuildFlagParam_None, Command__does_check &~ Command_test);
@@ -1002,7 +1004,9 @@ gb_internal bool parse_build_flags(Array<String> args) {
}
case BuildFlag_OptimizationMode: {
GB_ASSERT(value.kind == ExactValue_String);
if (value.value_string == "minimal") {
if (value.value_string == "none") {
build_context.optimization_level = -1;
} else if (value.value_string == "minimal") {
build_context.optimization_level = 0;
} else if (value.value_string == "size") {
build_context.optimization_level = 1;
@@ -1014,6 +1018,7 @@ gb_internal bool parse_build_flags(Array<String> args) {
gb_printf_err("\tminimal\n");
gb_printf_err("\tsize\n");
gb_printf_err("\tspeed\n");
gb_printf_err("\tnone (useful for -debug builds)\n");
bad_flags = true;
}
break;
@@ -1309,6 +1314,9 @@ gb_internal bool parse_build_flags(Array<String> args) {
case BuildFlag_NoEntryPoint:
build_context.no_entry_point = true;
break;
case BuildFlag_NoThreadLocal:
build_context.no_thread_local = true;
break;
case BuildFlag_UseLLD:
build_context.use_lld = true;
break;
@@ -1955,7 +1963,7 @@ gb_internal void print_show_help(String const arg0, String const &command) {
print_usage_line(1, "-o:<string>");
print_usage_line(2, "Set the optimization mode for compilation");
print_usage_line(2, "Accepted values: minimal, size, speed");
print_usage_line(2, "Accepted values: minimal, size, speed, none");
print_usage_line(2, "Example: -o:speed");
print_usage_line(0, "");
}
@@ -2061,6 +2069,10 @@ gb_internal void print_show_help(String const arg0, String const &command) {
print_usage_line(2, "Disables automatic linking with the C Run Time");
print_usage_line(0, "");
print_usage_line(1, "-no-thread-local");
print_usage_line(2, "Ignore @thread_local attribute, effectively treating the program as if it is single-threaded");
print_usage_line(0, "");
print_usage_line(1, "-lld");
print_usage_line(2, "Use the LLD linker rather than the default");
print_usage_line(0, "");