aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2023-09-27 11:38:11 +0100
committergingerBill <bill@gingerbill.org>2023-09-27 11:38:11 +0100
commitacc29fbcebf4459b1c98c54d9cc565d363a4196a (patch)
tree91b4692e0a8c9c3958ed44347ded5a2f40ee157d /src
parent94d68c1f225c3699d905388baee15e42ec6e49a0 (diff)
parentfc93ea7aa370d25aab61dab43e885f50978dff50 (diff)
Merge branch 'master' into llvm-17
Diffstat (limited to 'src')
-rw-r--r--src/check_builtin.cpp2
-rw-r--r--src/check_expr.cpp16
-rw-r--r--src/check_stmt.cpp2
-rw-r--r--src/check_type.cpp3
-rw-r--r--src/checker.cpp3
-rw-r--r--src/error.cpp37
-rw-r--r--src/llvm_backend_expr.cpp23
-rw-r--r--src/parser.cpp60
-rw-r--r--src/types.cpp42
9 files changed, 149 insertions, 39 deletions
diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp
index 2e65c5750..851665cb2 100644
--- a/src/check_builtin.cpp
+++ b/src/check_builtin.cpp
@@ -2120,7 +2120,7 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As
return false;
}
Type *t = o.type;
- if (t == nullptr || t == t_invalid || is_type_asm_proc(o.type) || is_type_polymorphic(operand->type)) {
+ if (t == nullptr || t == t_invalid || is_type_asm_proc(t) || is_type_polymorphic(t)) {
error(ce->args[0], "Invalid argument for '%.*s'", LIT(builtin_name));
return false;
}
diff --git a/src/check_expr.cpp b/src/check_expr.cpp
index 700412a86..968b6ec1e 100644
--- a/src/check_expr.cpp
+++ b/src/check_expr.cpp
@@ -2462,8 +2462,9 @@ gb_internal void add_comparison_procedures_for_fields(CheckerContext *c, Type *t
add_package_dependency(c, "runtime", "quaternion256_ne");
break;
case Basic_cstring:
- add_package_dependency(c, "runtime", "cstring_to_string");
- /*fallthrough*/
+ add_package_dependency(c, "runtime", "cstring_eq");
+ add_package_dependency(c, "runtime", "cstring_ne");
+ break;
case Basic_string:
add_package_dependency(c, "runtime", "string_eq");
add_package_dependency(c, "runtime", "string_ne");
@@ -2621,7 +2622,16 @@ gb_internal void check_comparison(CheckerContext *c, Ast *node, Operand *x, Oper
if (!is_type_untyped(x->type)) size = gb_max(size, type_size_of(x->type));
if (!is_type_untyped(y->type)) size = gb_max(size, type_size_of(y->type));
- if (is_type_string(x->type) || is_type_string(y->type)) {
+ if (is_type_cstring(x->type) && is_type_cstring(y->type)) {
+ switch (op) {
+ case Token_CmpEq: add_package_dependency(c, "runtime", "cstring_eq"); break;
+ case Token_NotEq: add_package_dependency(c, "runtime", "cstring_ne"); break;
+ case Token_Lt: add_package_dependency(c, "runtime", "cstring_lt"); break;
+ case Token_Gt: add_package_dependency(c, "runtime", "cstring_gt"); break;
+ case Token_LtEq: add_package_dependency(c, "runtime", "cstring_le"); break;
+ case Token_GtEq: add_package_dependency(c, "runtime", "cstring_gt"); break;
+ }
+ } else if (is_type_string(x->type) || is_type_string(y->type)) {
switch (op) {
case Token_CmpEq: add_package_dependency(c, "runtime", "string_eq"); break;
case Token_NotEq: add_package_dependency(c, "runtime", "string_ne"); break;
diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp
index cb1aa86ab..3f1b9611c 100644
--- a/src/check_stmt.cpp
+++ b/src/check_stmt.cpp
@@ -1893,7 +1893,7 @@ gb_internal void check_value_decl_stmt(CheckerContext *ctx, Ast *node, u32 mod_f
}
if (is_arch_wasm() && e->Variable.thread_local_model.len != 0) {
- error(e->token, "@(thread_local) is not supported for this target platform");
+ // error(e->token, "@(thread_local) is not supported for this target platform");
}
diff --git a/src/check_type.cpp b/src/check_type.cpp
index 5e7e76d66..a43c296a6 100644
--- a/src/check_type.cpp
+++ b/src/check_type.cpp
@@ -613,6 +613,9 @@ gb_internal void check_struct_type(CheckerContext *ctx, Type *struct_type, Ast *
scope_reserve(ctx->scope, min_field_count);
+ rw_mutex_lock(&struct_type->Struct.fields_mutex);
+ defer (rw_mutex_unlock(&struct_type->Struct.fields_mutex));
+
if (st->is_raw_union && min_field_count > 1) {
struct_type->Struct.is_raw_union = true;
context = str_lit("struct #raw_union");
diff --git a/src/checker.cpp b/src/checker.cpp
index 984a00a90..7182b6559 100644
--- a/src/checker.cpp
+++ b/src/checker.cpp
@@ -2029,6 +2029,9 @@ gb_internal void add_type_info_type_internal(CheckerContext *c, Type *t) {
break;
+ case Type_Generic:
+ break;
+
default:
GB_PANIC("Unhandled type: %*.s %d", LIT(type_strings[bt->kind]), bt->kind);
break;
diff --git a/src/error.cpp b/src/error.cpp
index 6a039006b..e63682829 100644
--- a/src/error.cpp
+++ b/src/error.cpp
@@ -356,7 +356,9 @@ gb_internal void error_out_coloured(char const *str, TerminalStyle style, Termin
gb_internal void error_va(TokenPos const &pos, TokenPos end, char const *fmt, va_list va) {
global_error_collector.count.fetch_add(1);
-
+ if (global_error_collector.count > MAX_ERROR_COLLECTOR_COUNT()) {
+ gb_exit(1);
+ }
mutex_lock(&global_error_collector.mutex);
// NOTE(bill): Duplicate error, skip it
if (pos.line == 0) {
@@ -372,11 +374,10 @@ gb_internal void error_va(TokenPos const &pos, TokenPos end, char const *fmt, va
error_out_va(fmt, va);
error_out("\n");
show_error_on_line(pos, end);
+ } else {
+ global_error_collector.count.fetch_sub(1);
}
mutex_unlock(&global_error_collector.mutex);
- if (global_error_collector.count > MAX_ERROR_COLLECTOR_COUNT()) {
- gb_exit(1);
- }
}
gb_internal void warning_va(TokenPos const &pos, TokenPos end, char const *fmt, va_list va) {
@@ -410,8 +411,11 @@ gb_internal void error_line_va(char const *fmt, va_list va) {
}
gb_internal void error_no_newline_va(TokenPos const &pos, char const *fmt, va_list va) {
- mutex_lock(&global_error_collector.mutex);
global_error_collector.count.fetch_add(1);
+ if (global_error_collector.count.load() > MAX_ERROR_COLLECTOR_COUNT()) {
+ gb_exit(1);
+ }
+ mutex_lock(&global_error_collector.mutex);
// NOTE(bill): Duplicate error, skip it
if (pos.line == 0) {
error_out_coloured("Error: ", TerminalStyle_Normal, TerminalColour_Red);
@@ -425,15 +429,15 @@ gb_internal void error_no_newline_va(TokenPos const &pos, char const *fmt, va_li
error_out_va(fmt, va);
}
mutex_unlock(&global_error_collector.mutex);
- if (global_error_collector.count.load() > MAX_ERROR_COLLECTOR_COUNT()) {
- gb_exit(1);
- }
}
gb_internal void syntax_error_va(TokenPos const &pos, TokenPos end, char const *fmt, va_list va) {
+ global_error_collector.count.fetch_add(1);
+ if (global_error_collector.count > MAX_ERROR_COLLECTOR_COUNT()) {
+ gb_exit(1);
+ }
mutex_lock(&global_error_collector.mutex);
- global_error_collector.count++;
// NOTE(bill): Duplicate error, skip it
if (global_error_collector.prev != pos) {
global_error_collector.prev = pos;
@@ -447,16 +451,14 @@ gb_internal void syntax_error_va(TokenPos const &pos, TokenPos end, char const *
error_out_va(fmt, va);
error_out("\n");
}
-
mutex_unlock(&global_error_collector.mutex);
- if (global_error_collector.count > MAX_ERROR_COLLECTOR_COUNT()) {
- gb_exit(1);
- }
}
gb_internal void syntax_error_with_verbose_va(TokenPos const &pos, TokenPos end, char const *fmt, va_list va) {
global_error_collector.count.fetch_add(1);
-
+ if (global_error_collector.count > MAX_ERROR_COLLECTOR_COUNT()) {
+ gb_exit(1);
+ }
mutex_lock(&global_error_collector.mutex);
// NOTE(bill): Duplicate error, skip it
if (pos.line == 0) {
@@ -474,9 +476,6 @@ gb_internal void syntax_error_with_verbose_va(TokenPos const &pos, TokenPos end,
show_error_on_line(pos, end);
}
mutex_unlock(&global_error_collector.mutex);
- if (global_error_collector.count > MAX_ERROR_COLLECTOR_COUNT()) {
- gb_exit(1);
- }
}
@@ -578,7 +577,3 @@ gb_internal void compiler_error(char const *fmt, ...) {
GB_DEBUG_TRAP();
gb_exit(1);
}
-
-
-
-
diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp
index e8569eba9..d6e8843fa 100644
--- a/src/llvm_backend_expr.cpp
+++ b/src/llvm_backend_expr.cpp
@@ -2414,7 +2414,28 @@ gb_internal lbValue lb_emit_comp(lbProcedure *p, TokenKind op_kind, lbValue left
}
if (is_type_string(a)) {
- if (is_type_cstring(a)) {
+ if (is_type_cstring(a) && is_type_cstring(b)) {
+ left = lb_emit_conv(p, left, t_cstring);
+ right = lb_emit_conv(p, right, t_cstring);
+ char const *runtime_procedure = nullptr;
+ switch (op_kind) {
+ case Token_CmpEq: runtime_procedure = "cstring_eq"; break;
+ case Token_NotEq: runtime_procedure = "cstring_ne"; break;
+ case Token_Lt: runtime_procedure = "cstring_lt"; break;
+ case Token_Gt: runtime_procedure = "cstring_gt"; break;
+ case Token_LtEq: runtime_procedure = "cstring_le"; break;
+ case Token_GtEq: runtime_procedure = "cstring_gt"; break;
+ }
+ GB_ASSERT(runtime_procedure != nullptr);
+
+ auto args = array_make<lbValue>(permanent_allocator(), 2);
+ args[0] = left;
+ args[1] = right;
+ return lb_emit_runtime_call(p, runtime_procedure, args);
+ }
+
+
+ if (is_type_cstring(a) ^ is_type_cstring(b)) {
left = lb_emit_conv(p, left, t_string);
right = lb_emit_conv(p, right, t_string);
}
diff --git a/src/parser.cpp b/src/parser.cpp
index cdf3c239c..a4bf949b9 100644
--- a/src/parser.cpp
+++ b/src/parser.cpp
@@ -1361,6 +1361,22 @@ gb_internal Token peek_token(AstFile *f) {
return {};
}
+gb_internal Token peek_token_n(AstFile *f, isize n) {
+ Token found = {};
+ for (isize i = f->curr_token_index+1; i < f->tokens.count; i++) {
+ Token tok = f->tokens[i];
+ if (tok.kind == Token_Comment) {
+ continue;
+ }
+ found = tok;
+ if (n-- == 0) {
+ return found;
+ }
+ }
+ return {};
+}
+
+
gb_internal bool skip_possible_newline(AstFile *f) {
if (token_is_newline(f->curr_token)) {
advance_token(f);
@@ -2206,6 +2222,10 @@ gb_internal Ast *parse_operand(AstFile *f, bool lhs) {
Ast *tag = ast_basic_directive(f, token, name);
Ast *original_expr = parse_expr(f, lhs);
Ast *expr = unparen_expr(original_expr);
+ if (expr == nullptr) {
+ syntax_error(name, "Expected a compound literal after #%.*s", LIT(name.string));
+ return ast_bad_expr(f, token, name);
+ }
switch (expr->kind) {
case Ast_ArrayType:
syntax_error(expr, "#partial has been replaced with #sparse for non-contiguous enumerated array types");
@@ -3419,6 +3439,18 @@ gb_internal Ast *parse_simple_stmt(AstFile *f, u32 flags) {
case Token_Colon:
expect_token_after(f, Token_Colon, "identifier list");
if ((flags&StmtAllowFlag_Label) && lhs.count == 1) {
+ bool is_partial = false;
+ Token partial_token = {};
+ if (f->curr_token.kind == Token_Hash) {
+ // NOTE(bill): This is purely for error messages
+ Token name = peek_token_n(f, 0);
+ if (name.kind == Token_Ident && name.string == "partial" &&
+ peek_token_n(f, 1).kind == Token_switch) {
+ partial_token = expect_token(f, Token_Hash);
+ expect_token(f, Token_Ident);
+ is_partial = true;
+ }
+ }
switch (f->curr_token.kind) {
case Token_OpenBrace: // block statement
case Token_if:
@@ -3440,6 +3472,19 @@ gb_internal Ast *parse_simple_stmt(AstFile *f, u32 flags) {
break;
}
#undef _SET_LABEL
+
+ if (is_partial) {
+ switch (stmt->kind) {
+ case Ast_SwitchStmt:
+ stmt->SwitchStmt.partial = true;
+ break;
+ case Ast_TypeSwitchStmt:
+ stmt->TypeSwitchStmt.partial = true;
+ break;
+ }
+ syntax_error(partial_token, "Incorrect use of directive, use '#partial %.*s: switch'", LIT(ast_token(name).string));
+ }
+
return stmt;
} break;
}
@@ -3984,7 +4029,9 @@ gb_internal Ast *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_fl
if (f->curr_token.kind != Token_Eq) {
type = parse_var_type(f, allow_ellipsis, allow_typeid_token);
Ast *tt = unparen_expr(type);
- if (is_signature && !any_polymorphic_names && tt->kind == Ast_TypeidType && tt->TypeidType.specialization != nullptr) {
+ if (is_signature && !any_polymorphic_names &&
+ tt != nullptr &&
+ tt->kind == Ast_TypeidType && tt->TypeidType.specialization != nullptr) {
syntax_error(type, "Specialization of typeid is not allowed without polymorphic names");
}
}
@@ -5941,6 +5988,16 @@ gb_internal ParseFileError process_imported_file(Parser *p, ImportedFile importe
}
}
+ {
+ String name = file->fullpath;
+ name = remove_directory_from_path(name);
+ name = remove_extension_from_path(name);
+
+ if (string_starts_with(name, str_lit("_"))) {
+ syntax_error(pos, "Files cannot start with '_', got '%.*s'", LIT(file->fullpath));
+ }
+ }
+
if (build_context.command_kind == Command_test) {
String name = file->fullpath;
name = remove_extension_from_path(name);
@@ -5951,6 +6008,7 @@ gb_internal ParseFileError process_imported_file(Parser *p, ImportedFile importe
}
}
+
if (parse_file(p, file)) {
MUTEX_GUARD_BLOCK(&pkg->files_mutex) {
array_add(&pkg->files, file);
diff --git a/src/types.cpp b/src/types.cpp
index 22deca1dc..f3062365f 100644
--- a/src/types.cpp
+++ b/src/types.cpp
@@ -143,7 +143,8 @@ struct TypeStruct {
Type * soa_elem;
i32 soa_count;
StructSoaKind soa_kind;
- BlockingMutex mutex; // for settings offsets
+ RwMutex fields_mutex;
+ BlockingMutex offset_mutex; // for settings offsets
bool is_polymorphic;
bool are_offsets_set : 1;
@@ -2645,10 +2646,14 @@ gb_internal bool are_types_identical_internal(Type *x, Type *y, bool check_tuple
return are_types_identical(x->Slice.elem, y->Slice.elem);
case Type_BitSet:
- return are_types_identical(x->BitSet.elem, y->BitSet.elem) &&
- are_types_identical(x->BitSet.underlying, y->BitSet.underlying) &&
- x->BitSet.lower == y->BitSet.lower &&
- x->BitSet.upper == y->BitSet.upper;
+ if (are_types_identical(x->BitSet.elem, y->BitSet.elem) &&
+ are_types_identical(x->BitSet.underlying, y->BitSet.underlying)) {
+ if (is_type_enum(x->BitSet.elem)) {
+ return true;
+ }
+ return x->BitSet.lower == y->BitSet.lower && x->BitSet.upper == y->BitSet.upper;
+ }
+ return false;
case Type_Enum:
@@ -2951,7 +2956,11 @@ gb_internal Selection lookup_field_from_index(Type *type, i64 index) {
gbAllocator a = permanent_allocator();
isize max_count = 0;
switch (type->kind) {
- case Type_Struct: max_count = type->Struct.fields.count; break;
+ case Type_Struct:
+ rw_mutex_shared_lock(&type->Struct.fields_mutex);
+ max_count = type->Struct.fields.count;
+ rw_mutex_shared_unlock(&type->Struct.fields_mutex);
+ break;
case Type_Tuple: max_count = type->Tuple.variables.count; break;
}
@@ -2960,7 +2969,9 @@ gb_internal Selection lookup_field_from_index(Type *type, i64 index) {
}
switch (type->kind) {
- case Type_Struct:
+ case Type_Struct: {
+ rw_mutex_shared_lock(&type->Struct.fields_mutex);
+ defer (rw_mutex_shared_unlock(&type->Struct.fields_mutex));
for (isize i = 0; i < max_count; i++) {
Entity *f = type->Struct.fields[i];
if (f->kind == Entity_Variable) {
@@ -2971,7 +2982,8 @@ gb_internal Selection lookup_field_from_index(Type *type, i64 index) {
}
}
}
- break;
+ } break;
+
case Type_Tuple:
for (isize i = 0; i < max_count; i++) {
Entity *f = type->Tuple.variables[i];
@@ -3024,7 +3036,10 @@ gb_internal Selection lookup_field_with_selection(Type *type_, String field_name
}
}
if (type->kind == Type_Struct) {
- for_array(i, type->Struct.fields) {
+ rw_mutex_shared_lock(&type->Struct.fields_mutex);
+ isize field_count = type->Struct.fields.count;
+ rw_mutex_shared_unlock(&type->Struct.fields_mutex);
+ if (field_count != 0) for_array(i, type->Struct.fields) {
Entity *f = type->Struct.fields[i];
if (f->flags&EntityFlag_Using) {
sel = lookup_field_with_selection(f->type, field_name, is_type, sel, allow_blank_ident);
@@ -3052,7 +3067,9 @@ gb_internal Selection lookup_field_with_selection(Type *type_, String field_name
}
if (type->kind == Type_Struct) {
+ rw_mutex_shared_lock(&type->Struct.fields_mutex);
Scope *s = type->Struct.scope;
+ rw_mutex_shared_unlock(&type->Struct.fields_mutex);
if (s != nullptr) {
Entity *found = scope_lookup_current(s, field_name);
if (found != nullptr && found->kind != Entity_Variable) {
@@ -3100,7 +3117,10 @@ gb_internal Selection lookup_field_with_selection(Type *type_, String field_name
}
}
- for_array(i, type->Struct.fields) {
+ rw_mutex_shared_lock(&type->Struct.fields_mutex);
+ isize field_count = type->Struct.fields.count;
+ rw_mutex_shared_unlock(&type->Struct.fields_mutex);
+ if (field_count != 0) for_array(i, type->Struct.fields) {
Entity *f = type->Struct.fields[i];
if (f->kind != Entity_Variable || (f->flags & EntityFlag_Field) == 0) {
continue;
@@ -3680,7 +3700,7 @@ gb_internal i64 *type_set_offsets_of(Slice<Entity *> const &fields, bool is_pack
gb_internal bool type_set_offsets(Type *t) {
t = base_type(t);
if (t->kind == Type_Struct) {
- MUTEX_GUARD(&t->Struct.mutex);
+ MUTEX_GUARD(&t->Struct.offset_mutex);
if (!t->Struct.are_offsets_set) {
t->Struct.are_offsets_being_processed = true;
t->Struct.offsets = type_set_offsets_of(t->Struct.fields, t->Struct.is_packed, t->Struct.is_raw_union);