mirror of
https://github.com/Ed94/Odin.git
synced 2026-07-02 18:11:49 -07:00
Merge branch 'master' into file-tags-without-comments
This commit is contained in:
@@ -919,6 +919,8 @@ gb_internal void report_os_info() {
|
||||
{"23F79", {23, 5, 0}, "macOS", {"Sonoma", {14, 5, 0}}},
|
||||
{"23G80", {23, 6, 0}, "macOS", {"Sonoma", {14, 6, 0}}},
|
||||
{"23G93", {23, 6, 0}, "macOS", {"Sonoma", {14, 6, 1}}},
|
||||
{"23H124", {23, 6, 0}, "macOS", {"Sonoma", {14, 7, 0}}},
|
||||
{"24A335", {24, 0, 0}, "macOS", {"Sequoia", {15, 0, 0}}},
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -285,6 +285,7 @@ enum VetFlags : u64 {
|
||||
VetFlag_Deprecated = 1u<<7,
|
||||
VetFlag_Cast = 1u<<8,
|
||||
VetFlag_Tabs = 1u<<9,
|
||||
VetFlag_UnusedProcedures = 1u<<10,
|
||||
|
||||
VetFlag_Unused = VetFlag_UnusedVariables|VetFlag_UnusedImports,
|
||||
|
||||
@@ -316,6 +317,8 @@ u64 get_vet_flag_from_name(String const &name) {
|
||||
return VetFlag_Cast;
|
||||
} else if (name == "tabs") {
|
||||
return VetFlag_Tabs;
|
||||
} else if (name == "unused-procedures") {
|
||||
return VetFlag_UnusedProcedures;
|
||||
}
|
||||
return VetFlag_NONE;
|
||||
}
|
||||
@@ -383,6 +386,7 @@ struct BuildContext {
|
||||
|
||||
u64 vet_flags;
|
||||
u32 sanitizer_flags;
|
||||
StringSet vet_packages;
|
||||
|
||||
bool has_resource;
|
||||
String link_flags;
|
||||
@@ -1462,8 +1466,6 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta
|
||||
bc->thread_count = gb_max(bc->affinity.thread_count, 1);
|
||||
}
|
||||
|
||||
string_set_init(&bc->custom_attributes);
|
||||
|
||||
bc->ODIN_VENDOR = str_lit("odin");
|
||||
bc->ODIN_VERSION = ODIN_VERSION;
|
||||
bc->ODIN_ROOT = odin_root_dir();
|
||||
|
||||
@@ -1632,6 +1632,22 @@ gb_internal bool check_builtin_procedure_directive(CheckerContext *c, Operand *o
|
||||
|
||||
operand->type = t_source_code_location;
|
||||
operand->mode = Addressing_Value;
|
||||
} else if (name == "caller_expression") {
|
||||
if (ce->args.count > 1) {
|
||||
error(ce->args[0], "'#caller_expression' expects either 0 or 1 arguments, got %td", ce->args.count);
|
||||
}
|
||||
if (ce->args.count > 0) {
|
||||
Ast *arg = ce->args[0];
|
||||
Operand o = {};
|
||||
Entity *e = check_ident(c, &o, arg, nullptr, nullptr, true);
|
||||
if (e == nullptr || (e->flags & EntityFlag_Param) == 0) {
|
||||
error(ce->args[0], "'#caller_expression' expected a valid earlier parameter name");
|
||||
}
|
||||
arg->Ident.entity = e;
|
||||
}
|
||||
|
||||
operand->type = t_string;
|
||||
operand->mode = Addressing_Value;
|
||||
} else if (name == "exists") {
|
||||
if (ce->args.count != 1) {
|
||||
error(ce->close, "'#exists' expects 1 argument, got %td", ce->args.count);
|
||||
|
||||
+6
-1
@@ -7807,7 +7807,8 @@ gb_internal ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *c
|
||||
name == "load" ||
|
||||
name == "load_directory" ||
|
||||
name == "load_hash" ||
|
||||
name == "hash"
|
||||
name == "hash" ||
|
||||
name == "caller_expression"
|
||||
) {
|
||||
operand->mode = Addressing_Builtin;
|
||||
operand->builtin_id = BuiltinProc_DIRECTIVE;
|
||||
@@ -8725,6 +8726,10 @@ gb_internal ExprKind check_basic_directive_expr(CheckerContext *c, Operand *o, A
|
||||
error(node, "#caller_location may only be used as a default argument parameter");
|
||||
o->type = t_source_code_location;
|
||||
o->mode = Addressing_Value;
|
||||
} else if (name == "caller_expression") {
|
||||
error(node, "#caller_expression may only be used as a default argument parameter");
|
||||
o->type = t_string;
|
||||
o->mode = Addressing_Value;
|
||||
} else {
|
||||
if (name == "location") {
|
||||
init_core_source_code_location(c->checker);
|
||||
|
||||
+14
-4
@@ -1641,6 +1641,8 @@ gb_internal void check_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags)
|
||||
|
||||
Ast *expr = unparen_expr(rs->expr);
|
||||
|
||||
Operand rhs_operand = {};
|
||||
|
||||
bool is_range = false;
|
||||
bool is_possibly_addressable = true;
|
||||
isize max_val_count = 2;
|
||||
@@ -1698,7 +1700,7 @@ gb_internal void check_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags)
|
||||
}
|
||||
}
|
||||
}
|
||||
bool is_ptr = is_type_pointer(type_deref(operand.type));
|
||||
bool is_ptr = is_type_pointer(operand.type);
|
||||
Type *t = base_type(type_deref(operand.type));
|
||||
|
||||
switch (t->kind) {
|
||||
@@ -1750,16 +1752,19 @@ gb_internal void check_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags)
|
||||
break;
|
||||
|
||||
case Type_DynamicArray:
|
||||
is_possibly_addressable = true;
|
||||
array_add(&vals, t->DynamicArray.elem);
|
||||
array_add(&vals, t_int);
|
||||
break;
|
||||
|
||||
case Type_Slice:
|
||||
is_possibly_addressable = true;
|
||||
array_add(&vals, t->Slice.elem);
|
||||
array_add(&vals, t_int);
|
||||
break;
|
||||
|
||||
case Type_Map:
|
||||
is_possibly_addressable = true;
|
||||
is_map = true;
|
||||
array_add(&vals, t->Map.key);
|
||||
array_add(&vals, t->Map.value);
|
||||
@@ -1781,6 +1786,8 @@ gb_internal void check_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags)
|
||||
|
||||
case Type_Tuple:
|
||||
{
|
||||
is_possibly_addressable = false;
|
||||
|
||||
isize count = t->Tuple.variables.count;
|
||||
if (count < 1) {
|
||||
ERROR_BLOCK();
|
||||
@@ -1810,8 +1817,6 @@ gb_internal void check_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags)
|
||||
array_add(&vals, e->type);
|
||||
}
|
||||
|
||||
is_possibly_addressable = false;
|
||||
|
||||
bool do_break = false;
|
||||
for (isize i = rs->vals.count-1; i >= 0; i--) {
|
||||
if (rs->vals[i] != nullptr && count < i+2) {
|
||||
@@ -1831,6 +1836,11 @@ gb_internal void check_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags)
|
||||
|
||||
case Type_Struct:
|
||||
if (t->Struct.soa_kind != StructSoa_None) {
|
||||
if (t->Struct.soa_kind == StructSoa_Fixed) {
|
||||
is_possibly_addressable = operand.mode == Addressing_Variable || is_ptr;
|
||||
} else {
|
||||
is_possibly_addressable = true;
|
||||
}
|
||||
is_soa = true;
|
||||
array_add(&vals, t->Struct.soa_elem);
|
||||
array_add(&vals, t_int);
|
||||
@@ -1907,7 +1917,7 @@ gb_internal void check_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags)
|
||||
if (is_possibly_addressable && i == addressable_index) {
|
||||
entity->flags &= ~EntityFlag_Value;
|
||||
} else {
|
||||
char const *idx_name = is_map ? "key" : is_bit_set ? "element" : "index";
|
||||
char const *idx_name = is_map ? "key" : (is_bit_set || i == 0) ? "element" : "index";
|
||||
error(token, "The %s variable '%.*s' cannot be made addressable", idx_name, LIT(str));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1605,6 +1605,25 @@ gb_internal bool is_expr_from_a_parameter(CheckerContext *ctx, Ast *expr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
gb_internal bool is_caller_expression(Ast *expr) {
|
||||
if (expr->kind == Ast_BasicDirective && expr->BasicDirective.name.string == "caller_expression") {
|
||||
return true;
|
||||
}
|
||||
|
||||
Ast *call = unparen_expr(expr);
|
||||
if (call->kind != Ast_CallExpr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ast_node(ce, CallExpr, call);
|
||||
if (ce->proc->kind != Ast_BasicDirective) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ast_node(bd, BasicDirective, ce->proc);
|
||||
String name = bd->name.string;
|
||||
return name == "caller_expression";
|
||||
}
|
||||
|
||||
gb_internal ParameterValue handle_parameter_value(CheckerContext *ctx, Type *in_type, Type **out_type_, Ast *expr, bool allow_caller_location) {
|
||||
ParameterValue param_value = {};
|
||||
@@ -1626,7 +1645,19 @@ gb_internal ParameterValue handle_parameter_value(CheckerContext *ctx, Type *in_
|
||||
if (in_type) {
|
||||
check_assignment(ctx, &o, in_type, str_lit("parameter value"));
|
||||
}
|
||||
} else if (is_caller_expression(expr)) {
|
||||
if (expr->kind != Ast_BasicDirective) {
|
||||
check_builtin_procedure_directive(ctx, &o, expr, t_string);
|
||||
}
|
||||
|
||||
param_value.kind = ParameterValue_Expression;
|
||||
o.type = t_string;
|
||||
o.mode = Addressing_Value;
|
||||
o.expr = expr;
|
||||
|
||||
if (in_type) {
|
||||
check_assignment(ctx, &o, in_type, str_lit("parameter value"));
|
||||
}
|
||||
} else {
|
||||
if (in_type) {
|
||||
check_expr_with_type_hint(ctx, &o, expr, in_type);
|
||||
@@ -1858,6 +1889,7 @@ gb_internal Type *check_get_params(CheckerContext *ctx, Scope *scope, Ast *_para
|
||||
case ParameterValue_Nil:
|
||||
break;
|
||||
case ParameterValue_Location:
|
||||
case ParameterValue_Expression:
|
||||
case ParameterValue_Value:
|
||||
gbString str = type_to_string(type);
|
||||
error(params[i], "A default value for a parameter must not be a polymorphic constant type, got %s", str);
|
||||
|
||||
+52
-19
@@ -533,18 +533,13 @@ gb_internal u64 check_vet_flags(CheckerContext *c) {
|
||||
c->curr_proc_decl->proc_lit) {
|
||||
file = c->curr_proc_decl->proc_lit->file();
|
||||
}
|
||||
if (file && file->vet_flags_set) {
|
||||
return file->vet_flags;
|
||||
}
|
||||
return build_context.vet_flags;
|
||||
|
||||
return ast_file_vet_flags(file);
|
||||
}
|
||||
|
||||
gb_internal u64 check_vet_flags(Ast *node) {
|
||||
AstFile *file = node->file();
|
||||
if (file && file->vet_flags_set) {
|
||||
return file->vet_flags;
|
||||
}
|
||||
return build_context.vet_flags;
|
||||
return ast_file_vet_flags(file);
|
||||
}
|
||||
|
||||
enum VettedEntityKind {
|
||||
@@ -681,20 +676,45 @@ gb_internal bool check_vet_unused(Checker *c, Entity *e, VettedEntity *ve) {
|
||||
return false;
|
||||
}
|
||||
|
||||
gb_internal void check_scope_usage(Checker *c, Scope *scope, u64 vet_flags) {
|
||||
bool vet_unused = (vet_flags & VetFlag_Unused) != 0;
|
||||
bool vet_shadowing = (vet_flags & (VetFlag_Shadowing|VetFlag_Using)) != 0;
|
||||
|
||||
gb_internal void check_scope_usage_internal(Checker *c, Scope *scope, u64 vet_flags, bool per_entity) {
|
||||
u64 original_vet_flags = vet_flags;
|
||||
Array<VettedEntity> vetted_entities = {};
|
||||
array_init(&vetted_entities, heap_allocator());
|
||||
defer (array_free(&vetted_entities));
|
||||
|
||||
rw_mutex_shared_lock(&scope->mutex);
|
||||
for (auto const &entry : scope->elements) {
|
||||
Entity *e = entry.value;
|
||||
if (e == nullptr) continue;
|
||||
|
||||
vet_flags = original_vet_flags;
|
||||
if (per_entity) {
|
||||
vet_flags = ast_file_vet_flags(e->file);
|
||||
}
|
||||
|
||||
bool vet_unused = (vet_flags & VetFlag_Unused) != 0;
|
||||
bool vet_shadowing = (vet_flags & (VetFlag_Shadowing|VetFlag_Using)) != 0;
|
||||
bool vet_unused_procedures = (vet_flags & VetFlag_UnusedProcedures) != 0;
|
||||
|
||||
VettedEntity ve_unused = {};
|
||||
VettedEntity ve_shadowed = {};
|
||||
bool is_unused = vet_unused && check_vet_unused(c, e, &ve_unused);
|
||||
bool is_unused = false;
|
||||
if (vet_unused && check_vet_unused(c, e, &ve_unused)) {
|
||||
is_unused = true;
|
||||
} else if (vet_unused_procedures &&
|
||||
e->kind == Entity_Procedure) {
|
||||
if (e->flags&EntityFlag_Used) {
|
||||
is_unused = false;
|
||||
} else if (e->flags & EntityFlag_Require) {
|
||||
is_unused = false;
|
||||
} else if (e->pkg && e->pkg->kind == Package_Init && e->token.string == "main") {
|
||||
is_unused = false;
|
||||
} else {
|
||||
is_unused = true;
|
||||
ve_unused.kind = VettedEntity_Unused;
|
||||
ve_unused.entity = e;
|
||||
}
|
||||
}
|
||||
bool is_shadowed = vet_shadowing && check_vet_shadowing(c, e, &ve_shadowed);
|
||||
if (is_unused && is_shadowed) {
|
||||
VettedEntity ve_both = ve_shadowed;
|
||||
@@ -717,13 +737,18 @@ gb_internal void check_scope_usage(Checker *c, Scope *scope, u64 vet_flags) {
|
||||
}
|
||||
rw_mutex_shared_unlock(&scope->mutex);
|
||||
|
||||
gb_sort(vetted_entities.data, vetted_entities.count, gb_size_of(VettedEntity), vetted_entity_variable_pos_cmp);
|
||||
array_sort(vetted_entities, vetted_entity_variable_pos_cmp);
|
||||
|
||||
for (auto const &ve : vetted_entities) {
|
||||
Entity *e = ve.entity;
|
||||
Entity *other = ve.other;
|
||||
String name = e->token.string;
|
||||
|
||||
vet_flags = original_vet_flags;
|
||||
if (per_entity) {
|
||||
vet_flags = ast_file_vet_flags(e->file);
|
||||
}
|
||||
|
||||
if (ve.kind == VettedEntity_Shadowed_And_Unused) {
|
||||
error(e->token, "'%.*s' declared but not used, possibly shadows declaration at line %d", LIT(name), other->token.pos.line);
|
||||
} else if (vet_flags) {
|
||||
@@ -732,6 +757,9 @@ gb_internal void check_scope_usage(Checker *c, Scope *scope, u64 vet_flags) {
|
||||
if (e->kind == Entity_Variable && (vet_flags & VetFlag_UnusedVariables) != 0) {
|
||||
error(e->token, "'%.*s' declared but not used", LIT(name));
|
||||
}
|
||||
if (e->kind == Entity_Procedure && (vet_flags & VetFlag_UnusedProcedures) != 0) {
|
||||
error(e->token, "'%.*s' declared but not used", LIT(name));
|
||||
}
|
||||
if ((e->kind == Entity_ImportName || e->kind == Entity_LibraryName) && (vet_flags & VetFlag_UnusedImports) != 0) {
|
||||
error(e->token, "'%.*s' declared but not used", LIT(name));
|
||||
}
|
||||
@@ -749,7 +777,11 @@ gb_internal void check_scope_usage(Checker *c, Scope *scope, u64 vet_flags) {
|
||||
}
|
||||
}
|
||||
|
||||
array_free(&vetted_entities);
|
||||
}
|
||||
|
||||
|
||||
gb_internal void check_scope_usage(Checker *c, Scope *scope, u64 vet_flags) {
|
||||
check_scope_usage_internal(c, scope, vet_flags, false);
|
||||
|
||||
for (Scope *child = scope->head_child; child != nullptr; child = child->next) {
|
||||
if (child->flags & (ScopeFlag_Proc|ScopeFlag_Type|ScopeFlag_File)) {
|
||||
@@ -6497,12 +6529,13 @@ gb_internal void check_parsed_files(Checker *c) {
|
||||
TIME_SECTION("check scope usage");
|
||||
for (auto const &entry : c->info.files) {
|
||||
AstFile *f = entry.value;
|
||||
u64 vet_flags = build_context.vet_flags;
|
||||
if (f->vet_flags_set) {
|
||||
vet_flags = f->vet_flags;
|
||||
}
|
||||
u64 vet_flags = ast_file_vet_flags(f);
|
||||
check_scope_usage(c, f->scope, vet_flags);
|
||||
}
|
||||
for (auto const &entry : c->info.packages) {
|
||||
AstPackage *pkg = entry.value;
|
||||
check_scope_usage_internal(c, pkg->scope, 0, true);
|
||||
}
|
||||
|
||||
TIME_SECTION("add basic type information");
|
||||
// Add "Basic" type information
|
||||
|
||||
@@ -104,6 +104,7 @@ enum ParameterValueKind {
|
||||
ParameterValue_Constant,
|
||||
ParameterValue_Nil,
|
||||
ParameterValue_Location,
|
||||
ParameterValue_Expression,
|
||||
ParameterValue_Value,
|
||||
};
|
||||
|
||||
|
||||
+10
-2
@@ -3195,11 +3195,11 @@ void gb_affinity_init(gbAffinity *a) {
|
||||
a->core_count = 1;
|
||||
a->threads_per_core = 1;
|
||||
|
||||
if (sysctlbyname("hw.logicalcpu", &count, &count_size, NULL, 0) == 0) {
|
||||
if (sysctlbyname("kern.smp.cpus", &count, &count_size, NULL, 0) == 0) {
|
||||
if (count > 0) {
|
||||
a->thread_count = count;
|
||||
// Get # of physical cores
|
||||
if (sysctlbyname("hw.physicalcpu", &count, &count_size, NULL, 0) == 0) {
|
||||
if (sysctlbyname("kern.smp.cores", &count, &count_size, NULL, 0) == 0) {
|
||||
if (count > 0) {
|
||||
a->core_count = count;
|
||||
a->threads_per_core = a->thread_count / count;
|
||||
@@ -3210,6 +3210,14 @@ void gb_affinity_init(gbAffinity *a) {
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (sysctlbyname("hw.ncpu", &count, &count_size, NULL, 0) == 0) {
|
||||
// SMP disabled or unavailable.
|
||||
if (count > 0) {
|
||||
a->is_accurate = true;
|
||||
a->thread_count = count;
|
||||
a->core_count = count;
|
||||
a->threads_per_core = 1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -528,7 +528,7 @@ gb_internal lbAddr lb_store_range_stmt_val(lbProcedure *p, Ast *stmt_val, lbValu
|
||||
gb_internal lbValue lb_emit_source_code_location_const(lbProcedure *p, String const &procedure, TokenPos const &pos);
|
||||
gb_internal lbValue lb_const_source_code_location_const(lbModule *m, String const &procedure, TokenPos const &pos);
|
||||
|
||||
gb_internal lbValue lb_handle_param_value(lbProcedure *p, Type *parameter_type, ParameterValue const ¶m_value, TokenPos const &pos);
|
||||
gb_internal lbValue lb_handle_param_value(lbProcedure *p, Type *parameter_type, ParameterValue const ¶m_value, TypeProc *procedure_type, Ast *call_expression);
|
||||
|
||||
gb_internal lbValue lb_equal_proc_for_type(lbModule *m, Type *type);
|
||||
gb_internal lbValue lb_hasher_proc_for_type(lbModule *m, Type *type);
|
||||
|
||||
+44
-36
@@ -552,6 +552,48 @@ gb_internal LLVMMetadataRef lb_debug_bitset(lbModule *m, Type *type, String name
|
||||
return final_decl;
|
||||
}
|
||||
|
||||
gb_internal LLVMMetadataRef lb_debug_bitfield(lbModule *m, Type *type, String name, LLVMMetadataRef scope, LLVMMetadataRef file, unsigned line) {
|
||||
Type *bt = base_type(type);
|
||||
GB_ASSERT(bt->kind == Type_BitField);
|
||||
|
||||
lb_debug_file_line(m, bt->BitField.node, &file, &line);
|
||||
|
||||
u64 size_in_bits = 8*type_size_of(bt);
|
||||
u32 align_in_bits = 8*cast(u32)type_align_of(bt);
|
||||
|
||||
unsigned element_count = cast(unsigned)bt->BitField.fields.count;
|
||||
LLVMMetadataRef *elements = gb_alloc_array(permanent_allocator(), LLVMMetadataRef, element_count);
|
||||
|
||||
u64 offset_in_bits = 0;
|
||||
for (unsigned i = 0; i < element_count; i++) {
|
||||
Entity *f = bt->BitField.fields[i];
|
||||
u8 bit_size = bt->BitField.bit_sizes[i];
|
||||
GB_ASSERT(f->kind == Entity_Variable);
|
||||
String name = f->token.string;
|
||||
elements[i] = LLVMDIBuilderCreateBitFieldMemberType(m->debug_builder, scope, cast(char const *)name.text, name.len, file, line,
|
||||
bit_size, offset_in_bits, 0,
|
||||
LLVMDIFlagZero, lb_debug_type(m, f->type)
|
||||
);
|
||||
|
||||
offset_in_bits += bit_size;
|
||||
}
|
||||
|
||||
LLVMMetadataRef final_decl = LLVMDIBuilderCreateStructType(
|
||||
m->debug_builder, scope,
|
||||
cast(char const *)name.text, cast(size_t)name.len,
|
||||
file, line,
|
||||
size_in_bits, align_in_bits,
|
||||
LLVMDIFlagZero,
|
||||
nullptr,
|
||||
elements, element_count,
|
||||
0,
|
||||
nullptr,
|
||||
"", 0
|
||||
);
|
||||
lb_set_llvm_metadata(m, type, final_decl);
|
||||
return final_decl;
|
||||
}
|
||||
|
||||
gb_internal LLVMMetadataRef lb_debug_enum(lbModule *m, Type *type, String name, LLVMMetadataRef scope, LLVMMetadataRef file, unsigned line) {
|
||||
Type *bt = base_type(type);
|
||||
GB_ASSERT(bt->kind == Type_Enum);
|
||||
@@ -816,6 +858,7 @@ gb_internal LLVMMetadataRef lb_debug_type_internal(lbModule *m, Type *type) {
|
||||
case Type_Union: return lb_debug_union( m, type, make_string_c(type_to_string(type, temporary_allocator())), nullptr, nullptr, 0);
|
||||
case Type_BitSet: return lb_debug_bitset( m, type, make_string_c(type_to_string(type, temporary_allocator())), nullptr, nullptr, 0);
|
||||
case Type_Enum: return lb_debug_enum( m, type, make_string_c(type_to_string(type, temporary_allocator())), nullptr, nullptr, 0);
|
||||
case Type_BitField: return lb_debug_bitfield( m, type, make_string_c(type_to_string(type, temporary_allocator())), nullptr, nullptr, 0);
|
||||
|
||||
case Type_Tuple:
|
||||
if (type->Tuple.variables.count == 1) {
|
||||
@@ -901,42 +944,6 @@ gb_internal LLVMMetadataRef lb_debug_type_internal(lbModule *m, Type *type) {
|
||||
lb_debug_type(m, type->Matrix.elem),
|
||||
subscripts, gb_count_of(subscripts));
|
||||
}
|
||||
|
||||
case Type_BitField: {
|
||||
LLVMMetadataRef parent_scope = nullptr;
|
||||
LLVMMetadataRef scope = nullptr;
|
||||
LLVMMetadataRef file = nullptr;
|
||||
unsigned line = 0;
|
||||
u64 size_in_bits = 8*cast(u64)type_size_of(type);
|
||||
u32 align_in_bits = 8*cast(u32)type_align_of(type);
|
||||
LLVMDIFlags flags = LLVMDIFlagZero;
|
||||
|
||||
unsigned element_count = cast(unsigned)type->BitField.fields.count;
|
||||
LLVMMetadataRef *elements = gb_alloc_array(permanent_allocator(), LLVMMetadataRef, element_count);
|
||||
|
||||
u64 offset_in_bits = 0;
|
||||
for (unsigned i = 0; i < element_count; i++) {
|
||||
Entity *f = type->BitField.fields[i];
|
||||
u8 bit_size = type->BitField.bit_sizes[i];
|
||||
GB_ASSERT(f->kind == Entity_Variable);
|
||||
String name = f->token.string;
|
||||
unsigned field_line = 0;
|
||||
LLVMDIFlags field_flags = LLVMDIFlagZero;
|
||||
elements[i] = LLVMDIBuilderCreateBitFieldMemberType(m->debug_builder, scope, cast(char const *)name.text, name.len, file, field_line,
|
||||
bit_size, offset_in_bits, offset_in_bits,
|
||||
field_flags, lb_debug_type(m, f->type)
|
||||
);
|
||||
|
||||
offset_in_bits += bit_size;
|
||||
}
|
||||
|
||||
|
||||
return LLVMDIBuilderCreateStructType(m->debug_builder, parent_scope, "", 0, file, line,
|
||||
size_in_bits, align_in_bits, flags,
|
||||
nullptr, elements, element_count, 0, nullptr,
|
||||
"", 0
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
GB_PANIC("Invalid type %s", type_to_string(type));
|
||||
@@ -1022,6 +1029,7 @@ gb_internal LLVMMetadataRef lb_debug_type(lbModule *m, Type *type) {
|
||||
case Type_Union: return lb_debug_union(m, type, name, scope, file, line);
|
||||
case Type_BitSet: return lb_debug_bitset(m, type, name, scope, file, line);
|
||||
case Type_Enum: return lb_debug_enum(m, type, name, scope, file, line);
|
||||
case Type_BitField: return lb_debug_bitfield(m, type, name, scope, file, line);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -699,7 +699,9 @@ gb_internal void lb_begin_procedure_body(lbProcedure *p) {
|
||||
}
|
||||
|
||||
if (e->Variable.param_value.kind != ParameterValue_Invalid) {
|
||||
lbValue c = lb_handle_param_value(p, e->type, e->Variable.param_value, e->token.pos);
|
||||
GB_ASSERT(e->Variable.param_value.kind != ParameterValue_Location);
|
||||
GB_ASSERT(e->Variable.param_value.kind != ParameterValue_Expression);
|
||||
lbValue c = lb_handle_param_value(p, e->type, e->Variable.param_value, nullptr, nullptr);
|
||||
lb_addr_store(p, res, c);
|
||||
}
|
||||
|
||||
@@ -3420,7 +3422,7 @@ gb_internal lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValu
|
||||
}
|
||||
|
||||
|
||||
gb_internal lbValue lb_handle_param_value(lbProcedure *p, Type *parameter_type, ParameterValue const ¶m_value, TokenPos const &pos) {
|
||||
gb_internal lbValue lb_handle_param_value(lbProcedure *p, Type *parameter_type, ParameterValue const ¶m_value, TypeProc *procedure_type, Ast* call_expression) {
|
||||
switch (param_value.kind) {
|
||||
case ParameterValue_Constant:
|
||||
if (is_type_constant_type(parameter_type)) {
|
||||
@@ -3446,8 +3448,60 @@ gb_internal lbValue lb_handle_param_value(lbProcedure *p, Type *parameter_type,
|
||||
if (p->entity != nullptr) {
|
||||
proc_name = p->entity->token.string;
|
||||
}
|
||||
|
||||
ast_node(ce, CallExpr, call_expression);
|
||||
TokenPos pos = ast_token(ce->proc).pos;
|
||||
|
||||
return lb_emit_source_code_location_as_global(p, proc_name, pos);
|
||||
}
|
||||
case ParameterValue_Expression:
|
||||
{
|
||||
Ast *orig = param_value.original_ast_expr;
|
||||
if (orig->kind == Ast_BasicDirective) {
|
||||
gbString expr = expr_to_string(call_expression, temporary_allocator());
|
||||
return lb_const_string(p->module, make_string_c(expr));
|
||||
}
|
||||
|
||||
isize param_idx = -1;
|
||||
String param_str = {0};
|
||||
{
|
||||
Ast *call = unparen_expr(orig);
|
||||
GB_ASSERT(call->kind == Ast_CallExpr);
|
||||
ast_node(ce, CallExpr, call);
|
||||
GB_ASSERT(ce->proc->kind == Ast_BasicDirective);
|
||||
GB_ASSERT(ce->args.count == 1);
|
||||
Ast *target = ce->args[0];
|
||||
GB_ASSERT(target->kind == Ast_Ident);
|
||||
String target_str = target->Ident.token.string;
|
||||
|
||||
param_idx = lookup_procedure_parameter(procedure_type, target_str);
|
||||
param_str = target_str;
|
||||
}
|
||||
GB_ASSERT(param_idx >= 0);
|
||||
|
||||
|
||||
Ast *target_expr = nullptr;
|
||||
ast_node(ce, CallExpr, call_expression);
|
||||
|
||||
if (ce->split_args->positional.count > param_idx) {
|
||||
target_expr = ce->split_args->positional[param_idx];
|
||||
}
|
||||
|
||||
for_array(i, ce->split_args->named) {
|
||||
Ast *arg = ce->split_args->named[i];
|
||||
ast_node(fv, FieldValue, arg);
|
||||
GB_ASSERT(fv->field->kind == Ast_Ident);
|
||||
String name = fv->field->Ident.token.string;
|
||||
if (name == param_str) {
|
||||
target_expr = fv->value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
gbString expr = expr_to_string(target_expr, temporary_allocator());
|
||||
return lb_const_string(p->module, make_string_c(expr));
|
||||
}
|
||||
|
||||
case ParameterValue_Value:
|
||||
return lb_build_expr(p, param_value.ast_value);
|
||||
}
|
||||
@@ -3739,8 +3793,6 @@ gb_internal lbValue lb_build_call_expr_internal(lbProcedure *p, Ast *expr) {
|
||||
}
|
||||
}
|
||||
|
||||
TokenPos pos = ast_token(ce->proc).pos;
|
||||
|
||||
|
||||
if (pt->params != nullptr) {
|
||||
isize min_count = pt->params->Tuple.variables.count;
|
||||
@@ -3764,7 +3816,7 @@ gb_internal lbValue lb_build_call_expr_internal(lbProcedure *p, Ast *expr) {
|
||||
args[arg_index] = lb_const_nil(p->module, e->type);
|
||||
break;
|
||||
case Entity_Variable:
|
||||
args[arg_index] = lb_handle_param_value(p, e->type, e->Variable.param_value, pos);
|
||||
args[arg_index] = lb_handle_param_value(p, e->type, e->Variable.param_value, pt, expr);
|
||||
break;
|
||||
|
||||
case Entity_Constant:
|
||||
|
||||
+49
-2
@@ -340,12 +340,14 @@ enum BuildFlagKind {
|
||||
BuildFlag_VetUnused,
|
||||
BuildFlag_VetUnusedImports,
|
||||
BuildFlag_VetUnusedVariables,
|
||||
BuildFlag_VetUnusedProcedures,
|
||||
BuildFlag_VetUsingStmt,
|
||||
BuildFlag_VetUsingParam,
|
||||
BuildFlag_VetStyle,
|
||||
BuildFlag_VetSemicolon,
|
||||
BuildFlag_VetCast,
|
||||
BuildFlag_VetTabs,
|
||||
BuildFlag_VetPackages,
|
||||
|
||||
BuildFlag_CustomAttribute,
|
||||
BuildFlag_IgnoreUnknownAttributes,
|
||||
@@ -547,6 +549,7 @@ gb_internal bool parse_build_flags(Array<String> args) {
|
||||
add_flag(&build_flags, BuildFlag_Vet, str_lit("vet"), BuildFlagParam_None, Command__does_check);
|
||||
add_flag(&build_flags, BuildFlag_VetUnused, str_lit("vet-unused"), BuildFlagParam_None, Command__does_check);
|
||||
add_flag(&build_flags, BuildFlag_VetUnusedVariables, str_lit("vet-unused-variables"), BuildFlagParam_None, Command__does_check);
|
||||
add_flag(&build_flags, BuildFlag_VetUnusedProcedures, str_lit("vet-unused-procedures"), BuildFlagParam_None, Command__does_check);
|
||||
add_flag(&build_flags, BuildFlag_VetUnusedImports, str_lit("vet-unused-imports"), BuildFlagParam_None, Command__does_check);
|
||||
add_flag(&build_flags, BuildFlag_VetShadowing, str_lit("vet-shadowing"), BuildFlagParam_None, Command__does_check);
|
||||
add_flag(&build_flags, BuildFlag_VetUsingStmt, str_lit("vet-using-stmt"), BuildFlagParam_None, Command__does_check);
|
||||
@@ -555,6 +558,7 @@ gb_internal bool parse_build_flags(Array<String> args) {
|
||||
add_flag(&build_flags, BuildFlag_VetSemicolon, str_lit("vet-semicolon"), BuildFlagParam_None, Command__does_check);
|
||||
add_flag(&build_flags, BuildFlag_VetCast, str_lit("vet-cast"), BuildFlagParam_None, Command__does_check);
|
||||
add_flag(&build_flags, BuildFlag_VetTabs, str_lit("vet-tabs"), BuildFlagParam_None, Command__does_check);
|
||||
add_flag(&build_flags, BuildFlag_VetPackages, str_lit("vet-packages"), BuildFlagParam_String, Command__does_check);
|
||||
|
||||
add_flag(&build_flags, BuildFlag_CustomAttribute, str_lit("custom-attribute"), BuildFlagParam_String, Command__does_check, true);
|
||||
add_flag(&build_flags, BuildFlag_IgnoreUnknownAttributes, str_lit("ignore-unknown-attributes"), BuildFlagParam_None, Command__does_check);
|
||||
@@ -1220,6 +1224,36 @@ gb_internal bool parse_build_flags(Array<String> args) {
|
||||
case BuildFlag_VetSemicolon: build_context.vet_flags |= VetFlag_Semicolon; break;
|
||||
case BuildFlag_VetCast: build_context.vet_flags |= VetFlag_Cast; break;
|
||||
case BuildFlag_VetTabs: build_context.vet_flags |= VetFlag_Tabs; break;
|
||||
case BuildFlag_VetUnusedProcedures:
|
||||
build_context.vet_flags |= VetFlag_UnusedProcedures;
|
||||
if (!set_flags[BuildFlag_VetPackages]) {
|
||||
gb_printf_err("-%.*s must be used with -vet-packages\n", LIT(name));
|
||||
bad_flags = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case BuildFlag_VetPackages:
|
||||
{
|
||||
GB_ASSERT(value.kind == ExactValue_String);
|
||||
String val = value.value_string;
|
||||
String_Iterator it = {val, 0};
|
||||
for (;;) {
|
||||
String pkg = string_split_iterator(&it, ',');
|
||||
if (pkg.len == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
pkg = string_trim_whitespace(pkg);
|
||||
if (!string_is_valid_identifier(pkg)) {
|
||||
gb_printf_err("-%.*s '%.*s' must be a valid identifier\n", LIT(name), LIT(pkg));
|
||||
bad_flags = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
string_set_add(&build_context.vet_packages, pkg);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case BuildFlag_CustomAttribute:
|
||||
{
|
||||
@@ -1234,7 +1268,7 @@ gb_internal bool parse_build_flags(Array<String> args) {
|
||||
|
||||
attr = string_trim_whitespace(attr);
|
||||
if (!string_is_valid_identifier(attr)) {
|
||||
gb_printf_err("-custom-attribute '%.*s' must be a valid identifier\n", LIT(attr));
|
||||
gb_printf_err("-%.*s '%.*s' must be a valid identifier\n", LIT(name), LIT(attr));
|
||||
bad_flags = true;
|
||||
continue;
|
||||
}
|
||||
@@ -2364,7 +2398,7 @@ gb_internal void print_show_help(String const arg0, String const &command) {
|
||||
print_usage_line(0, "");
|
||||
|
||||
print_usage_line(1, "-vet-unused");
|
||||
print_usage_line(2, "Checks for unused declarations.");
|
||||
print_usage_line(2, "Checks for unused declarations (variables and imports).");
|
||||
print_usage_line(0, "");
|
||||
|
||||
print_usage_line(1, "-vet-unused-variables");
|
||||
@@ -2406,6 +2440,16 @@ gb_internal void print_show_help(String const arg0, String const &command) {
|
||||
print_usage_line(1, "-vet-tabs");
|
||||
print_usage_line(2, "Errs when the use of tabs has not been used for indentation.");
|
||||
print_usage_line(0, "");
|
||||
|
||||
print_usage_line(1, "-vet-packages:<comma-separated-strings>");
|
||||
print_usage_line(2, "Sets which packages by name will be vetted.");
|
||||
print_usage_line(2, "Files with specific +vet tags will not be ignored if they are not in the packages set.");
|
||||
print_usage_line(0, "");
|
||||
|
||||
print_usage_line(1, "-vet-unused-procedures");
|
||||
print_usage_line(2, "Checks for unused procedures.");
|
||||
print_usage_line(2, "Must be used with -vet-packages or specified on a per file with +vet tags.");
|
||||
print_usage_line(0, "");
|
||||
}
|
||||
|
||||
if (check) {
|
||||
@@ -3150,6 +3194,9 @@ int main(int arg_count, char const **arg_ptr) {
|
||||
|
||||
build_context.command = command;
|
||||
|
||||
string_set_init(&build_context.custom_attributes);
|
||||
string_set_init(&build_context.vet_packages);
|
||||
|
||||
if (!parse_build_flags(args)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
+20
-11
@@ -1,10 +1,28 @@
|
||||
#include "parser_pos.cpp"
|
||||
|
||||
gb_internal bool in_vet_packages(AstFile *file) {
|
||||
if (file == nullptr) {
|
||||
return true;
|
||||
}
|
||||
if (file->pkg == nullptr) {
|
||||
return true;
|
||||
}
|
||||
if (build_context.vet_packages.entries.count == 0) {
|
||||
return true;
|
||||
}
|
||||
return string_set_exists(&build_context.vet_packages, file->pkg->name);
|
||||
}
|
||||
|
||||
gb_internal u64 ast_file_vet_flags(AstFile *f) {
|
||||
if (f != nullptr && f->vet_flags_set) {
|
||||
return f->vet_flags;
|
||||
}
|
||||
return build_context.vet_flags;
|
||||
|
||||
bool found = in_vet_packages(f);
|
||||
if (found) {
|
||||
return build_context.vet_flags;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
gb_internal bool ast_file_vet_style(AstFile *f) {
|
||||
@@ -5378,18 +5396,9 @@ gb_internal Ast *parse_stmt(AstFile *f) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
gb_internal u64 check_vet_flags(AstFile *file) {
|
||||
if (file && file->vet_flags_set) {
|
||||
return file->vet_flags;
|
||||
}
|
||||
return build_context.vet_flags;
|
||||
}
|
||||
|
||||
|
||||
gb_internal void parse_enforce_tabs(AstFile *f) {
|
||||
// Checks to see if tabs have been used for indentation
|
||||
if ((check_vet_flags(f) & VetFlag_Tabs) == 0) {
|
||||
if ((ast_file_vet_flags(f) & VetFlag_Tabs) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user