From 684945ea57da61c82ab5425930c5571157359cfb Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 23 Feb 2019 17:45:30 +0000 Subject: Fix calling conventions for simd vector types --- src/check_type.cpp | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) (limited to 'src/check_type.cpp') diff --git a/src/check_type.cpp b/src/check_type.cpp index 953eebdda..8b6b67e65 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -1790,6 +1790,10 @@ Type *type_to_abi_compat_param_type(gbAllocator a, Type *original_type) { return new_type; } + if (is_type_simd_vector(original_type)) { + return new_type; + } + if (build_context.ODIN_OS == "windows") { // NOTE(bill): Changing the passing parameter value type is to match C's ABI // IMPORTANT TODO(bill): This only matches the ABI on MSVC at the moment @@ -1893,7 +1897,11 @@ Type *type_to_abi_compat_result_type(gbAllocator a, Type *original_type) { } GB_ASSERT(is_type_tuple(original_type)); + Type *single_type = reduce_tuple_to_single_type(original_type); + if (is_type_simd_vector(single_type)) { + return new_type; + } if (build_context.ODIN_OS == "windows") { Type *bt = core_type(reduce_tuple_to_single_type(original_type)); @@ -1941,15 +1949,16 @@ Type *type_to_abi_compat_result_type(gbAllocator a, Type *original_type) { return new_type; } -bool abi_compat_return_by_value(gbAllocator a, ProcCallingConvention cc, Type *abi_return_type) { +bool abi_compat_return_by_pointer(gbAllocator a, ProcCallingConvention cc, Type *abi_return_type) { if (abi_return_type == nullptr) { return false; } - // switch (cc) { - // case ProcCC_Odin: - // case ProcCC_Contextless: - // return false; - // } + + Type *single_type = reduce_tuple_to_single_type(abi_return_type); + + if (is_type_simd_vector(single_type)) { + return false; + } if (build_context.ODIN_OS == "windows") { @@ -2075,7 +2084,7 @@ bool check_procedure_type(CheckerContext *ctx, Type *type, Ast *proc_type_node, // NOTE(bill): The types are the same type->Proc.abi_compat_result_type = type_to_abi_compat_result_type(c->allocator, type->Proc.results); - type->Proc.return_by_pointer = abi_compat_return_by_value(c->allocator, pt->calling_convention, type->Proc.abi_compat_result_type); + type->Proc.return_by_pointer = abi_compat_return_by_pointer(c->allocator, pt->calling_convention, type->Proc.abi_compat_result_type); return success; } -- cgit v1.2.3 From e551d2b25ea39afb95f7b8ee4309ef0cc8b502b8 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 23 Feb 2019 21:39:47 +0000 Subject: Replace `foreign export {}` with `@export` --- src/check_decl.cpp | 11 ++++++----- src/check_expr.cpp | 16 ++++++++++++++++ src/check_type.cpp | 6 +++++- src/checker.cpp | 54 ++++++++++++++++++++++++++++++++++++++++-------------- src/checker.hpp | 2 +- src/parser.cpp | 10 ++-------- src/tokenizer.cpp | 1 - 7 files changed, 70 insertions(+), 30 deletions(-) (limited to 'src/check_type.cpp') diff --git a/src/check_decl.cpp b/src/check_decl.cpp index 91fd0ff01..e9d6d5860 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -551,20 +551,20 @@ void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) { check_procedure_type(&tmp_ctx, proc_type, pl->type); TypeProc *pt = &proc_type->Proc; - - bool is_foreign = e->Procedure.is_foreign; - bool is_export = e->Procedure.is_export; - bool is_require_results = (pl->tags & ProcTag_require_results) != 0; - AttributeContext ac = make_attribute_context(e->Procedure.link_prefix); if (d != nullptr) { check_decl_attributes(ctx, d->attributes, proc_decl_attribute, &ac); } + e->Procedure.is_export = ac.is_export; e->deprecated_message = ac.deprecated_message; ac.link_name = handle_link_name(ctx, e->token, ac.link_name, ac.link_prefix); + bool is_foreign = e->Procedure.is_foreign; + bool is_export = e->Procedure.is_export; + bool is_require_results = (pl->tags & ProcTag_require_results) != 0; + if (e->pkg != nullptr && e->token.string == "main") { if (pt->param_count != 0 || pt->result_count != 0) { @@ -718,6 +718,7 @@ void check_var_decl(CheckerContext *ctx, Entity *e, Ast *type_expr, Ast *init_ex check_decl_attributes(ctx, decl->attributes, var_decl_attribute, &ac); } + e->Variable.is_export = ac.is_export; ac.link_name = handle_link_name(ctx, e->token, ac.link_name, ac.link_prefix); e->Variable.thread_local_model = ac.thread_local_model; diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 75c16b705..ea125a5eb 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -1241,6 +1241,14 @@ bool check_binary_op(CheckerContext *c, Operand *o, Token op) { error(op, "Operator '%.*s' is only allowed with integers", LIT(op.string)); return false; } + if (is_type_simd_vector(o->type)) { + switch (op.kind) { + case Token_ModMod: + case Token_ModModEq: + error(op, "Operator '%.*s' is only allowed with integers", LIT(op.string)); + return false; + } + } break; case Token_AndNot: @@ -1249,6 +1257,14 @@ bool check_binary_op(CheckerContext *c, Operand *o, Token op) { error(op, "Operator '%.*s' is only allowed with integers and bit sets", LIT(op.string)); return false; } + if (is_type_simd_vector(o->type)) { + switch (op.kind) { + case Token_AndNot: + case Token_AndNotEq: + error(op, "Operator '%.*s' is only allowed with integers", LIT(op.string)); + return false; + } + } break; case Token_CmpAnd: diff --git a/src/check_type.cpp b/src/check_type.cpp index 8b6b67e65..1c5d5ac85 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -1783,7 +1783,11 @@ Type *type_to_abi_compat_param_type(gbAllocator a, Type *original_type) { Type *new_type = original_type; if (is_type_boolean(original_type)) { - return t_llvm_bool; + Type *t = core_type(base_type(new_type)); + if (t == t_bool) { + return t_llvm_bool; + } + return new_type; } if (build_context.ODIN_ARCH == "386") { diff --git a/src/checker.cpp b/src/checker.cpp index 7900555a5..9bbe64839 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -1952,7 +1952,18 @@ DECL_ATTRIBUTE_PROC(foreign_block_decl_attribute) { } DECL_ATTRIBUTE_PROC(proc_decl_attribute) { - if (name == "deferred") { + if (name == "export") { + ExactValue ev = check_decl_attribute_value(c, value); + if (ev.kind == ExactValue_Invalid) { + ac->is_export = true; + } else if (ev.kind == ExactValue_Bool) { + ac->is_export = ev.value_bool; + } else { + error(value, "Expected either a boolean or no parameter for 'export'"); + return false; + } + return true; + } else if (name == "deferred") { if (value != nullptr) { Operand o = {}; check_expr(c, &o, value); @@ -2064,7 +2075,20 @@ DECL_ATTRIBUTE_PROC(var_decl_attribute) { return true; } - if (name == "link_name") { + if (name == "export") { + ExactValue ev = check_decl_attribute_value(c, value); + if (ev.kind == ExactValue_Invalid) { + ac->is_export = true; + } else if (ev.kind == ExactValue_Bool) { + ac->is_export = ev.value_bool; + } else { + error(value, "Expected either a boolean or no parameter for 'export'"); + return false; + } + if (ac->thread_local_model != "") { + error(elem, "An exported variable cannot be thread local"); + } + } else if (name == "link_name") { if (ev.kind == ExactValue_String) { ac->link_name = ev.value_string; if (!is_foreign_name_valid(ac->link_name)) { @@ -2087,8 +2111,10 @@ DECL_ATTRIBUTE_PROC(var_decl_attribute) { } else if (name == "thread_local") { if (ac->init_expr_list_count > 0) { error(elem, "A thread local variable declaration cannot have initialization values"); - } else if (c->foreign_context.curr_library || c->foreign_context.in_export) { + } else if (c->foreign_context.curr_library) { error(elem, "A foreign block variable cannot be thread local"); + } else if (ac->is_export) { + error(elem, "An exported variable cannot be thread local"); } else if (ev.kind == ExactValue_Invalid) { ac->thread_local_model = str_lit("default"); } else if (ev.kind == ExactValue_String) { @@ -2151,9 +2177,17 @@ void check_decl_attributes(CheckerContext *c, Array const &attributes, De case_ast_node(i, Ident, elem); name = i->token.string; case_end; + case_ast_node(i, Implicit, elem); + name = i->string; + case_end; case_ast_node(fv, FieldValue, elem); - GB_ASSERT(fv->field->kind == Ast_Ident); - name = fv->field->Ident.token.string; + if (fv->field->kind == Ast_Ident) { + name = fv->field->Ident.token.string; + } else if (fv->field->kind == Ast_Implicit) { + name = fv->field->Implicit.string; + } else { + GB_PANIC("Unknown Field Value name"); + } value = fv->value; case_end; default: @@ -2407,9 +2441,6 @@ void check_collect_value_decl(CheckerContext *c, Ast *decl) { e->Variable.foreign_library_ident = fl; e->Variable.link_prefix = c->foreign_context.link_prefix; - - } else if (c->foreign_context.in_export) { - e->Variable.is_export = true; } Ast *init_expr = value; @@ -2475,9 +2506,6 @@ void check_collect_value_decl(CheckerContext *c, Ast *decl) { GB_ASSERT(cc != ProcCC_Invalid); pl->type->ProcType.calling_convention = cc; - - } else if (c->foreign_context.in_export) { - e->Procedure.is_export = true; } d->proc_lit = init; d->type_expr = pl->type; @@ -2516,7 +2544,7 @@ void check_collect_value_decl(CheckerContext *c, Ast *decl) { } if (e->kind != Entity_Procedure) { - if (fl != nullptr || c->foreign_context.in_export) { + if (fl != nullptr) { AstKind kind = init->kind; error(name, "Only procedures and variables are allowed to be in a foreign block, got %.*s", LIT(ast_strings[kind])); if (kind == Ast_ProcType) { @@ -2544,8 +2572,6 @@ void check_add_foreign_block_decl(CheckerContext *ctx, Ast *decl) { CheckerContext c = *ctx; if (foreign_library->kind == Ast_Ident) { c.foreign_context.curr_library = foreign_library; - } else if (foreign_library->kind == Ast_Implicit && foreign_library->Implicit.kind == Token_export) { - c.foreign_context.in_export = true; } else { error(foreign_library, "Foreign block name must be an identifier or 'export'"); c.foreign_context.curr_library = nullptr; diff --git a/src/checker.hpp b/src/checker.hpp index de491671e..759e343bf 100644 --- a/src/checker.hpp +++ b/src/checker.hpp @@ -305,6 +305,7 @@ struct DeferredProcedure { struct AttributeContext { + bool is_export; String link_name; String link_prefix; isize init_expr_list_count; @@ -423,7 +424,6 @@ struct ForeignContext { Ast * curr_library; ProcCallingConvention default_cc; String link_prefix; - bool in_export; }; typedef Array CheckerTypePath; diff --git a/src/parser.cpp b/src/parser.cpp index e38c34a0a..9d42b3828 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -1199,7 +1199,6 @@ void fix_advance_to_next_stmt(AstFile *f) { case Token_package: case Token_foreign: case Token_import: - case Token_export: case Token_if: case Token_for: @@ -2452,9 +2451,7 @@ void parse_foreign_block_decl(AstFile *f, Array *decls) { Ast *parse_foreign_block(AstFile *f, Token token) { CommentGroup *docs = f->lead_comment; Ast *foreign_library = nullptr; - if (f->curr_token.kind == Token_export) { - foreign_library = ast_implicit(f, expect_token(f, Token_export)); - } else if (f->curr_token.kind == Token_OpenBrace) { + if (f->curr_token.kind == Token_OpenBrace) { foreign_library = ast_ident(f, blank_token); } else { foreign_library = parse_ident(f); @@ -3590,7 +3587,6 @@ Ast *parse_foreign_decl(AstFile *f) { Token token = expect_token(f, Token_foreign); switch (f->curr_token.kind) { - case Token_export: case Token_Ident: case Token_OpenBrace: return parse_foreign_block(f, token); @@ -3667,6 +3663,7 @@ Ast *parse_attribute(AstFile *f, Token token, TokenKind open_kind, TokenKind clo f->curr_token.kind != Token_EOF) { Ast *elem = nullptr; elem = parse_ident(f); + if (f->curr_token.kind == Token_Eq) { Token eq = expect_token(f, Token_Eq); Ast *value = parse_value(f); @@ -3732,9 +3729,6 @@ Ast *parse_stmt(AstFile *f) { case Token_import: return parse_import_decl(f, ImportDecl_Standard); - // case Token_export: - // return parse_export_decl(f); - case Token_if: return parse_if_stmt(f); case Token_when: return parse_when_stmt(f); diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp index 02770e371..31afe3d2e 100644 --- a/src/tokenizer.cpp +++ b/src/tokenizer.cpp @@ -82,7 +82,6 @@ TOKEN_KIND(Token__OperatorEnd, ""), \ \ TOKEN_KIND(Token__KeywordBegin, ""), \ TOKEN_KIND(Token_import, "import"), \ - TOKEN_KIND(Token_export, "export"), \ TOKEN_KIND(Token_foreign, "foreign"), \ TOKEN_KIND(Token_package, "package"), \ TOKEN_KIND(Token_typeid, "typeid"), \ -- cgit v1.2.3 From bdab5e00da6dee80b7582135815f2183def935bb Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 11 Mar 2019 19:52:40 +0000 Subject: Minor code clean up --- core/odin/parser/parser.odin | 27 +++++++++++++++++++++++++-- core/runtime/core.odin | 30 ++++++++++++------------------ src/check_expr.cpp | 3 ++- src/check_type.cpp | 1 + src/parser.hpp | 1 - src/types.cpp | 1 + 6 files changed, 41 insertions(+), 22 deletions(-) (limited to 'src/check_type.cpp') diff --git a/core/odin/parser/parser.odin b/core/odin/parser/parser.odin index 17a24c5f5..ccae59a7c 100644 --- a/core/odin/parser/parser.odin +++ b/core/odin/parser/parser.odin @@ -1077,9 +1077,9 @@ parse_stmt :: proc(p: ^Parser) -> ^ast.Stmt { stmt := parse_stmt(p); switch name { case "bounds_check": - stmt.state_flags |= {ast.Node_State_Flag.Bounds_Check}; + stmt.state_flags |= {.Bounds_Check}; case "no_bounds_check": - stmt.state_flags |= {ast.Node_State_Flag.No_Bounds_Check}; + stmt.state_flags |= {.No_Bounds_Check}; } return stmt; case "complete": @@ -1723,6 +1723,29 @@ string_to_calling_convention :: proc(s: string) -> ast.Proc_Calling_Convention { return Invalid; } +parse_proc_tags :: proc(p: ^Parser) -> (tags: Proc_Tags) { + for p.curr_tok.kind == token.Hash { + tok := expect_token(p, token.Hash); + ident := expect_token(p, token.Ident); + + switch ident.text { + case "require_results": + tags |= {.Require_Results}; + case "bounds_check": + tags |= {.Bounds_Check}; + case "no_bounds_check": + tags |= {.No_Bounds_Check}; + case: + } + } + + if .Bounds_Check in tags && .No_Bounds_Check in tags { + p.err(p.curr_tok.pos, "#bounds_check and #no_bounds_check applied to the same procedure type"); + } + + return; +} + parse_proc_type :: proc(p: ^Parser, tok: token.Token) -> ^ast.Proc_Type { cc := ast.Proc_Calling_Convention.Invalid; if p.curr_tok.kind == token.String { diff --git a/core/runtime/core.odin b/core/runtime/core.odin index 38dd8f225..1ce7cfac5 100644 --- a/core/runtime/core.odin +++ b/core/runtime/core.odin @@ -251,8 +251,10 @@ Map_Entry_Header :: struct { Map_Header :: struct { m: ^mem.Raw_Map, is_key_string: bool, + entry_size: int, entry_align: int, + value_offset: uintptr, value_size: int, } @@ -833,29 +835,23 @@ __get_map_key :: proc "contextless" (key: $K) -> Map_Key { return map_key; } +_fnv64a :: proc(data: []byte, seed: u64 = 0xcbf29ce484222325) -> u64 { + h: u64 = seed; + for b in data { + h = (h ~ u64(b)) * 0x100000001b3; + } + return h; +} + default_hash :: proc(data: []byte) -> u64 { - fnv64a :: proc(data: []byte) -> u64 { - h: u64 = 0xcbf29ce484222325; - for b in data { - h = (h ~ u64(b)) * 0x100000001b3; - } - return h; - } - return fnv64a(data); + return _fnv64a(data); } default_hash_string :: proc(s: string) -> u64 do return default_hash(([]byte)(s)); source_code_location_hash :: proc(s: Source_Code_Location) -> u64 { - fnv64a :: proc(data: []byte, seed: u64 = 0xcbf29ce484222325) -> u64 { - h: u64 = seed; - for b in data { - h = (h ~ u64(b)) * 0x100000001b3; - } - return h; - } - hash := fnv64a(cast([]byte)s.file_path); + hash := _fnv64a(cast([]byte)s.file_path); hash = hash ~ (u64(s.line) * 0x100000001b3); hash = hash ~ (u64(s.column) * 0x100000001b3); return hash; @@ -863,7 +859,6 @@ source_code_location_hash :: proc(s: Source_Code_Location) -> u64 { - __slice_resize :: proc(array_: ^$T/[]$E, new_count: int, allocator: mem.Allocator, loc := #caller_location) -> bool { array := (^mem.Raw_Slice)(array_); @@ -942,7 +937,6 @@ __dynamic_map_get :: proc(h: Map_Header, key: Map_Key) -> rawptr { } __dynamic_map_set :: proc(h: Map_Header, key: Map_Key, value: rawptr, loc := #caller_location) #no_bounds_check { - index: int; assert(value != nil); diff --git a/src/check_expr.cpp b/src/check_expr.cpp index f533a1812..d0e18d89f 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -5439,7 +5439,8 @@ ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *call) { operand->mode = Addressing_NoValue; } else { GB_ASSERT(is_type_tuple(result_type)); - switch (result_type->Tuple.variables.count) { + isize count = result_type->Tuple.variables.count; + switch (count) { case 0: operand->mode = Addressing_NoValue; break; diff --git a/src/check_type.cpp b/src/check_type.cpp index 1c5d5ac85..451a388fb 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -2049,6 +2049,7 @@ bool check_procedure_type(CheckerContext *ctx, Type *type, Ast *proc_type_node, type->Proc.is_polymorphic = pt->generic; type->Proc.specialization_count = specialization_count; type->Proc.diverging = pt->diverging; + type->Proc.tags = pt->tags; if (param_count > 0) { Entity *end = params->Tuple.variables[param_count-1]; diff --git a/src/parser.hpp b/src/parser.hpp index 816f3f534..e08648eca 100644 --- a/src/parser.hpp +++ b/src/parser.hpp @@ -151,7 +151,6 @@ enum ProcTag { ProcTag_bounds_check = 1<<0, ProcTag_no_bounds_check = 1<<1, ProcTag_require_results = 1<<4, - ProcTag_no_context = 1<<6, }; enum ProcCallingConvention { diff --git a/src/types.cpp b/src/types.cpp index c6886e984..5aa2ab6e1 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -198,6 +198,7 @@ struct TypeUnion { bool has_proc_default_values; \ bool has_named_results; \ bool diverging; /* no return */ \ + u64 tags; \ isize specialization_count; \ ProcCallingConvention calling_convention; \ }) \ -- cgit v1.2.3