From f917935f9d0110bb276e5a1fffad02c6a4ae84ea Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 19 Feb 2019 10:04:36 +0000 Subject: Disallow compound literals for `struct #raw_union` (fix) --- src/check_expr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/check_expr.cpp') diff --git a/src/check_expr.cpp b/src/check_expr.cpp index e5140ce25..79f980a79 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -5778,7 +5778,7 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type if (cl->elems.count == 0) { break; // NOTE(bill): No need to init } - if (!is_type_struct(t)) { + if (t->Struct.is_raw_union) { if (cl->elems.count != 0) { gbString type_str = type_to_string(type); error(node, "Illegal compound literal type '%s'", type_str); -- cgit v1.2.3 From 4c51384ad64a2f63863e6bacab7aeee881659047 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 23 Feb 2019 16:44:16 +0000 Subject: `intrinsics.vector` type (Experimental) --- core/fmt/fmt.odin | 24 +++++++++ core/runtime/core.odin | 8 ++- core/types/types.odin | 5 ++ src/check_expr.cpp | 54 +++++++++++++++++++ src/checker.cpp | 19 +++++++ src/checker.hpp | 5 ++ src/ir.cpp | 13 +++++ src/ir_print.cpp | 35 ++++++++++++ src/types.cpp | 144 ++++++++++++++++++++++++++++--------------------- 9 files changed, 246 insertions(+), 61 deletions(-) (limited to 'src/check_expr.cpp') diff --git a/core/fmt/fmt.odin b/core/fmt/fmt.odin index c4a535d77..0df06c0ec 100644 --- a/core/fmt/fmt.odin +++ b/core/fmt/fmt.odin @@ -1008,6 +1008,20 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) { fmt_arg(fi, any{rawptr(data), info.elem.id}, verb); } + case runtime.Type_Info_Simd_Vector: + if info.is_x86_mmx { + strings.write_string(fi.buf, "intrinsics.x86_mmx<>"); + } + strings.write_byte(fi.buf, '<'); + defer strings.write_byte(fi.buf, '>'); + for i in 0..info.count-1 { + if i > 0 do strings.write_string(fi.buf, ", "); + + data := uintptr(v.data) + uintptr(i*info.elem_size); + fmt_arg(fi, any{rawptr(data), info.elem.id}, verb); + } + + case runtime.Type_Info_Slice: strings.write_byte(fi.buf, '['); defer strings.write_byte(fi.buf, ']'); @@ -1448,5 +1462,15 @@ write_type :: proc(buf: ^strings.Builder, ti: ^runtime.Type_Info) { write_string(buf, "opaque "); write_type(buf, info.elem); + case runtime.Type_Info_Simd_Vector: + if info.is_x86_mmx { + write_string(buf, "intrinsics.x86_mmx"); + } else { + write_string(buf, "intrinsics.vector("); + write_i64(buf, i64(info.count)); + write_string(buf, ", "); + write_type(buf, info.elem); + write_byte(buf, ')'); + } } } diff --git a/core/runtime/core.odin b/core/runtime/core.odin index 9307b5589..38dd8f225 100644 --- a/core/runtime/core.odin +++ b/core/runtime/core.odin @@ -112,9 +112,14 @@ Type_Info_Bit_Set :: struct { lower: i64, upper: i64, }; - Type_Info_Opaque :: struct { elem: ^Type_Info, +}; +Type_Info_Simd_Vector :: struct { + elem: ^Type_Info, + elem_size: int, + count: int, + is_x86_mmx: bool, } Type_Info :: struct { @@ -145,6 +150,7 @@ Type_Info :: struct { Type_Info_Bit_Field, Type_Info_Bit_Set, Type_Info_Opaque, + Type_Info_Simd_Vector, }, } diff --git a/core/types/types.odin b/core/types/types.odin index 485530fea..dc4db549f 100644 --- a/core/types/types.odin +++ b/core/types/types.odin @@ -267,3 +267,8 @@ is_opaque :: proc(info: ^rt.Type_Info) -> bool { _, ok := rt.type_info_base(info).variant.(rt.Type_Info_Opaque); return ok; } +is_simd_vector :: proc(info: ^rt.Type_Info) -> bool { + if info == nil do return false; + _, ok := rt.type_info_base(info).variant.(rt.Type_Info_Simd_Vector); + return ok; +} diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 79f980a79..75c16b705 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -4072,6 +4072,46 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 break; } + case BuiltinProc_vector: { + Operand x = {}; + Operand y = {}; + x = *operand; + if (!is_type_integer(x.type) || x.mode != Addressing_Constant) { + error(call, "Expected a constant integer for 'intrinsics.vector'"); + operand->mode = Addressing_Type; + operand->type = t_invalid; + return false; + } + if (x.value.value_integer.neg) { + error(call, "Negative vector element length"); + operand->mode = Addressing_Type; + operand->type = t_invalid; + return false; + } + i64 count = big_int_to_i64(&x.value.value_integer); + + check_expr_or_type(c, &y, ce->args[1]); + if (y.mode != Addressing_Type) { + error(call, "Expected a type 'intrinsics.vector'"); + operand->mode = Addressing_Type; + operand->type = t_invalid; + return false; + } + Type *elem = y.type; + if (!is_type_valid_vector_elem(elem)) { + gbString str = type_to_string(elem); + error(call, "Invalid element type for 'intrinsics.vector', expected an integer or float with no specific endianness, got '%s'", str); + gb_string_free(str); + operand->mode = Addressing_Type; + operand->type = t_invalid; + return false; + } + + operand->mode = Addressing_Type; + operand->type = alloc_type_simd_vector(count, elem); + break; + } + case BuiltinProc_atomic_fence: case BuiltinProc_atomic_fence_acq: case BuiltinProc_atomic_fence_rel: @@ -5902,6 +5942,7 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type case Type_Slice: case Type_Array: case Type_DynamicArray: + case Type_SimdVector: { Type *elem_type = nullptr; String context_name = {}; @@ -5922,6 +5963,10 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type add_package_dependency(c, "runtime", "__dynamic_array_reserve"); add_package_dependency(c, "runtime", "__dynamic_array_append"); + } else if (t->kind == Type_SimdVector) { + elem_type = t->SimdVector.elem; + context_name = str_lit("simd vector literal"); + max_type_count = t->SimdVector.count; } else { GB_PANIC("unreachable"); } @@ -5972,6 +6017,15 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type error(node, "Expected %lld values for this array literal, got %lld", cast(long long)t->Array.count, cast(long long)max); } } + + if (t->kind == Type_SimdVector) { + if (!is_constant) { + error(node, "Expected all constant elements for a simd vector"); + } + if (t->SimdVector.is_x86_mmx) { + error(node, "Compound literals are not allowed with intrinsics.x86_mmx"); + } + } break; } diff --git a/src/checker.cpp b/src/checker.cpp index 9cac82911..7900555a5 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -712,6 +712,15 @@ void init_universal(void) { } } + // TODO(bill): Set the correct arch for this + if (bc->metrics.arch == TargetArch_amd64 || bc->metrics.arch == TargetArch_386) { + t_vector_x86_mmx = alloc_type(Type_SimdVector); + t_vector_x86_mmx->SimdVector.is_x86_mmx = true; + + Entity *entity = alloc_entity(Entity_TypeName, nullptr, make_token_ident(str_lit("x86_mmx")), t_vector_x86_mmx); + add_global_entity(entity, intrinsics_pkg->scope); + } + t_u8_ptr = alloc_type_pointer(t_u8); t_int_ptr = alloc_type_pointer(t_int); @@ -1248,6 +1257,10 @@ void add_type_info_type(CheckerContext *c, Type *t) { add_type_info_type(c, bt->Proc.results); break; + case Type_SimdVector: + add_type_info_type(c, bt->SimdVector.elem); + break; + default: GB_PANIC("Unhandled type: %*.s %d", LIT(type_strings[bt->kind]), bt->kind); break; @@ -1419,6 +1432,10 @@ void add_min_dep_type_info(Checker *c, Type *t) { add_min_dep_type_info(c, bt->Proc.results); break; + case Type_SimdVector: + add_min_dep_type_info(c, bt->SimdVector.elem); + break; + default: GB_PANIC("Unhandled type: %*.s", LIT(type_strings[bt->kind])); break; @@ -1795,6 +1812,7 @@ void init_core_type_info(Checker *c) { t_type_info_bit_field = find_core_type(c, str_lit("Type_Info_Bit_Field")); t_type_info_bit_set = find_core_type(c, str_lit("Type_Info_Bit_Set")); t_type_info_opaque = find_core_type(c, str_lit("Type_Info_Opaque")); + t_type_info_simd_vector = find_core_type(c, str_lit("Type_Info_Simd_Vector")); t_type_info_named_ptr = alloc_type_pointer(t_type_info_named); t_type_info_integer_ptr = alloc_type_pointer(t_type_info_integer); @@ -1818,6 +1836,7 @@ void init_core_type_info(Checker *c) { t_type_info_bit_field_ptr = alloc_type_pointer(t_type_info_bit_field); t_type_info_bit_set_ptr = alloc_type_pointer(t_type_info_bit_set); t_type_info_opaque_ptr = alloc_type_pointer(t_type_info_opaque); + t_type_info_simd_vector_ptr = alloc_type_pointer(t_type_info_simd_vector); } void init_mem_allocator(Checker *c) { diff --git a/src/checker.hpp b/src/checker.hpp index abc349129..de491671e 100644 --- a/src/checker.hpp +++ b/src/checker.hpp @@ -89,6 +89,8 @@ enum BuiltinProcId { BuiltinProc_DIRECTIVE, // NOTE(bill): This is used for specialized hash-prefixed procedures // "Intrinsics" + BuiltinProc_vector, + BuiltinProc_atomic_fence, BuiltinProc_atomic_fence_acq, BuiltinProc_atomic_fence_rel, @@ -194,6 +196,9 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = { // "Intrinsics" + {STR_LIT("vector"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, // Type + + {STR_LIT("atomic_fence"), 0, false, Expr_Stmt, BuiltinProcPkg_intrinsics}, {STR_LIT("atomic_fence_acq"), 0, false, Expr_Stmt, BuiltinProcPkg_intrinsics}, {STR_LIT("atomic_fence_rel"), 0, false, Expr_Stmt, BuiltinProcPkg_intrinsics}, diff --git a/src/ir.cpp b/src/ir.cpp index cd7e8d99a..4df6665f7 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -7268,6 +7268,7 @@ irAddr ir_build_addr(irProcedure *proc, Ast *expr) { case Type_Array: et = bt->Array.elem; break; case Type_Slice: et = bt->Slice.elem; break; case Type_BitSet: et = bt->BitSet.elem; break; + case Type_SimdVector: et = bt->SimdVector.elem; break; } String proc_name = {}; @@ -9995,6 +9996,18 @@ void ir_setup_type_info_data(irProcedure *proc) { // NOTE(bill): Setup type_info tag = ir_emit_conv(proc, variant_ptr, t_type_info_opaque_ptr); ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 0), ir_get_type_info_ptr(proc, t->Opaque.elem)); break; + + case Type_SimdVector: + ir_emit_comment(proc, str_lit("Type_SimdVector")); + tag = ir_emit_conv(proc, variant_ptr, t_type_info_simd_vector_ptr); + if (t->SimdVector.is_x86_mmx) { + ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 3), v_true); + } else { + ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 0), ir_get_type_info_ptr(proc, t->SimdVector.elem)); + ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 1), ir_const_int(type_size_of(t->SimdVector.elem))); + ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 2), ir_const_int(t->SimdVector.count)); + } + break; } diff --git a/src/ir_print.cpp b/src/ir_print.cpp index c6e717f74..0cc9f52e3 100644 --- a/src/ir_print.cpp +++ b/src/ir_print.cpp @@ -574,6 +574,16 @@ void ir_print_type(irFileBuffer *f, irModule *m, Type *t, bool in_struct) { case Type_Opaque: ir_print_type(f, m, strip_opaque_type(t)); return; + + case Type_SimdVector: + if (t->SimdVector.is_x86_mmx) { + ir_write_str_lit(f, "x86_mmx"); + } else { + ir_fprintf(f, "<%lld x ", t->SimdVector.count);; + ir_print_type(f, m, t->SimdVector.elem); + ir_write_byte(f, '>'); + } + return; } } @@ -802,6 +812,31 @@ void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type * } ir_write_byte(f, ']'); + } else if (is_type_simd_vector(type)) { + ast_node(cl, CompoundLit, value.value_compound); + + Type *elem_type = type->SimdVector.elem; + isize elem_count = cl->elems.count; + if (elem_count == 0) { + ir_write_str_lit(f, "zeroinitializer"); + break; + } + GB_ASSERT_MSG(elem_count == type->SimdVector.count, "%td != %td", elem_count, type->SimdVector.count); + + ir_write_byte(f, '<'); + + for (isize i = 0; i < elem_count; i++) { + if (i > 0) ir_write_str_lit(f, ", "); + TypeAndValue tav = cl->elems[i]->tav; + GB_ASSERT(tav.mode != Addressing_Invalid); + ir_print_compound_element(f, m, tav.value, elem_type); + } + for (isize i = elem_count; i < type->SimdVector.count; i++) { + if (i >= elem_count) ir_write_str_lit(f, ", "); + ir_print_compound_element(f, m, empty_exact_value, elem_type); + } + + ir_write_byte(f, '>'); } else if (is_type_struct(type)) { gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&m->tmp_arena); defer (gb_temp_arena_memory_end(tmp)); diff --git a/src/types.cpp b/src/types.cpp index 859805f29..6dcbf029f 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -215,6 +215,12 @@ struct TypeUnion { i64 lower; \ i64 upper; \ }) \ + TYPE_KIND(SimdVector, struct { \ + i64 count; \ + Type *elem; \ + bool is_x86_mmx; \ + }) \ + @@ -460,13 +466,13 @@ gb_global Type *t_type_info_map = nullptr; gb_global Type *t_type_info_bit_field = nullptr; gb_global Type *t_type_info_bit_set = nullptr; gb_global Type *t_type_info_opaque = nullptr; +gb_global Type *t_type_info_simd_vector = nullptr; gb_global Type *t_type_info_named_ptr = nullptr; gb_global Type *t_type_info_integer_ptr = nullptr; gb_global Type *t_type_info_rune_ptr = nullptr; gb_global Type *t_type_info_float_ptr = nullptr; gb_global Type *t_type_info_complex_ptr = nullptr; -gb_global Type *t_type_info_quaternion_ptr = nullptr; gb_global Type *t_type_info_any_ptr = nullptr; gb_global Type *t_type_info_typeid_ptr = nullptr; gb_global Type *t_type_info_string_ptr = nullptr; @@ -484,6 +490,7 @@ gb_global Type *t_type_info_map_ptr = nullptr; gb_global Type *t_type_info_bit_field_ptr = nullptr; gb_global Type *t_type_info_bit_set_ptr = nullptr; gb_global Type *t_type_info_opaque_ptr = nullptr; +gb_global Type *t_type_info_simd_vector_ptr = nullptr; gb_global Type *t_allocator = nullptr; gb_global Type *t_allocator_ptr = nullptr; @@ -496,6 +503,8 @@ gb_global Type *t_source_code_location_ptr = nullptr; gb_global Type *t_map_key = nullptr; gb_global Type *t_map_header = nullptr; +gb_global Type *t_vector_x86_mmx = nullptr; + i64 type_size_of (Type *t); @@ -722,6 +731,13 @@ Type *alloc_type_bit_set() { +Type *alloc_type_simd_vector(i64 count, Type *elem) { + Type *t = alloc_type(Type_SimdVector); + t->SimdVector.count = count; + t->SimdVector.elem = elem; + return t; +} + //////////////////////////////////////////////////////////////// @@ -971,6 +987,11 @@ bool is_type_generic(Type *t) { return t->kind == Type_Generic; } +bool is_type_simd_vector(Type *t) { + t = base_type(t); + return t->kind == Type_SimdVector; +} + Type *core_array_type(Type *t) { for (;;) { @@ -1193,6 +1214,25 @@ Type *bit_set_to_int(Type *t) { return nullptr; } +bool is_type_valid_vector_elem(Type *t) { + t = base_type(t); + if (t->kind == Type_Basic) { + if (t->Basic.flags & BasicFlag_EndianLittle) { + return false; + } + if (t->Basic.flags & BasicFlag_EndianBig) { + return false; + } + if (is_type_integer(t)) { + return true; + } + if (is_type_float(t)) { + return true; + } + } + return false; +} + bool is_type_indexable(Type *t) { Type *bt = base_type(t); @@ -1637,6 +1677,18 @@ bool are_types_identical(Type *x, Type *y) { are_types_identical(x->Map.value, y->Map.value); } break; + + case Type_SimdVector: + if (y->kind == Type_SimdVector) { + if (x->SimdVector.is_x86_mmx == y->SimdVector.is_x86_mmx) { + if (x->SimdVector.is_x86_mmx) { + return true; + } else if (x->SimdVector.count == y->SimdVector.count) { + return are_types_identical(x->SimdVector.elem, y->SimdVector.elem); + } + } + } + break; } return false; @@ -1681,65 +1733,6 @@ Type *default_type(Type *type) { return type; } -/* -// NOTE(bill): Valid Compile time execution #run type -bool is_type_cte_safe(Type *type) { - type = default_type(base_type(type)); - switch (type->kind) { - case Type_Basic: - switch (type->Basic.kind) { - case Basic_rawptr: - case Basic_any: - return false; - } - return true; - - case Type_Pointer: - return false; - - case Type_Array: - return is_type_cte_safe(type->Array.elem); - - case Type_DynamicArray: - return false; - case Type_Map: - return false; - - case Type_Slice: - return false; - - case Type_Struct: { - if (type->Struct.is_raw_union) { - return false; - } - for_array(i, type->Struct.fields) { - Entity *v = type->Struct.fields[i]; - if (!is_type_cte_safe(v->type)) { - return false; - } - } - return true; - } - - case Type_Tuple: { - for_array(i, type->Tuple.variables) { - Entity *v = type->Tuple.variables[i]; - if (!is_type_cte_safe(v->type)) { - return false; - } - } - return true; - } - - case Type_Proc: - // TODO(bill): How should I handle procedures in the CTE stage? - // return type->Proc.calling_convention == ProcCC_Odin; - return false; - } - - return false; -} - */ i64 union_variant_index(Type *u, Type *v) { u = base_type(u); GB_ASSERT(u->kind == Type_Union); @@ -2389,7 +2382,18 @@ i64 type_align_of_internal(Type *t, TypePath *path) { if (bits <= 32) return 4; if (bits <= 64) return 8; return 8; // NOTE(bill): Could be an invalid range so limit it for now + } + case Type_SimdVector: { + if (t->SimdVector.is_x86_mmx) { + return 8; + } + // align of + i64 count = t->SimdVector.count; + Type *elem = t->SimdVector.elem; + i64 size = count * type_size_of_internal(elem, path); + // IMPORTANT TODO(bill): Figure out the alignment of vector types + return gb_clamp(next_pow2(type_size_of_internal(t, path)), 1, build_context.max_align); } } @@ -2622,6 +2626,15 @@ i64 type_size_of_internal(Type *t, TypePath *path) { if (bits <= 64) return 8; return 8; // NOTE(bill): Could be an invalid range so limit it for now } + + case Type_SimdVector: { + if (t->SimdVector.is_x86_mmx) { + return 8; + } + i64 count = t->SimdVector.count; + Type *elem = t->SimdVector.elem; + return count * type_size_of_internal(elem, path); + } } // Catch all @@ -2950,6 +2963,17 @@ gbString write_type_to_string(gbString str, Type *type) { } str = gb_string_appendc(str, "]"); break; + + case Type_SimdVector: + if (type->SimdVector.is_x86_mmx) { + return "intrinsics.x86_mmx"; + } else { + str = gb_string_appendc(str, "intrinsics.vector("); + str = gb_string_append_fmt(str, "%d, ", cast(int)type->SimdVector.count); + str = write_type_to_string(str, type->SimdVector.elem); + str = gb_string_appendc(str, ")"); + } + break; } return str; -- 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_expr.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 ad3b6ab71854a638f2b769fc12e8776abfff48d6 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 6 Mar 2019 16:19:47 +0000 Subject: Implicit Selector Expressions: `.A` --- core/odin/ast/ast.odin | 4 ++++ core/odin/parser/parser.odin | 7 +++++++ src/check_expr.cpp | 49 ++++++++++++++++++++++++++++++++++++++++++-- src/ir.cpp | 7 +++++++ src/parser.cpp | 24 +++++++++++++++++++++- src/parser.hpp | 1 + 6 files changed, 89 insertions(+), 3 deletions(-) (limited to 'src/check_expr.cpp') diff --git a/core/odin/ast/ast.odin b/core/odin/ast/ast.odin index 8c43ee8e3..59d18a0c0 100644 --- a/core/odin/ast/ast.odin +++ b/core/odin/ast/ast.odin @@ -144,6 +144,10 @@ Selector_Expr :: struct { field: ^Ident, } +Implicit_Selector_Expr :: struct { + using node: Expr, + field: ^Ident, +} Index_Expr :: struct { using node: Expr, diff --git a/core/odin/parser/parser.odin b/core/odin/parser/parser.odin index c10a83e47..90de2ca30 100644 --- a/core/odin/parser/parser.odin +++ b/core/odin/parser/parser.odin @@ -2581,6 +2581,13 @@ parse_unary_expr :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr { ue.expr = expr; return ue; + case token.Period: + op := advance_token(p); + field := parse_ident(p); + ise := ast.new(ast.Implicit_Selector_Expr, op.pos, field.end); + ise.field = field; + return ise; + } return parse_atom_expr(p, parse_operand(p, lhs), lhs); } diff --git a/src/check_expr.cpp b/src/check_expr.cpp index ea125a5eb..4c921f484 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -991,7 +991,6 @@ Entity *check_ident(CheckerContext *c, Operand *o, Ast *n, Type *named_type, Typ o->expr = n; String name = n->Ident.token.string; - Entity *e = scope_lookup(c->scope, name); if (e == nullptr) { if (is_blank_ident(name)) { @@ -6177,7 +6176,7 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type continue; } - check_expr(c, o, elem); + check_expr_with_type_hint(c, o, elem, et); if (is_constant) { is_constant = o->mode == Addressing_Constant; @@ -6408,6 +6407,47 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type case_end; + case_ast_node(ise, ImplicitSelectorExpr, node); + o->type = t_invalid; + o->expr = node; + o->mode = Addressing_Invalid; + + if (type_hint == nullptr) { + gbString str = expr_to_string(node); + error(node, "Cannot determine type for implicit selector expression '%s'", str); + gb_string_free(str); + return Expr_Expr; + } + o->type = type_hint; + if (!is_type_enum(type_hint)) { + gbString typ = type_to_string(type_hint); + gbString str = expr_to_string(node); + error(node, "Invalid type '%s' for implicit selector expression '%s'", typ, str); + gb_string_free(str); + gb_string_free(typ); + return Expr_Expr; + } + GB_ASSERT(ise->selector->kind == Ast_Ident); + String name = ise->selector->Ident.token.string; + + Type *enum_type = base_type(type_hint); + GB_ASSERT(enum_type->kind == Type_Enum); + Entity *e = scope_lookup_current(enum_type->Enum.scope, name); + if (e == nullptr) { + gbString typ = type_to_string(type_hint); + error(node, "Undeclared name %.*s for type '%s'", LIT(name), typ); + gb_string_free(typ); + return Expr_Expr; + } + GB_ASSERT(are_types_identical(base_type(e->type), base_type(type_hint))); + GB_ASSERT(e->kind == Entity_Constant); + o->value = e->Constant.value; + o->mode = Addressing_Constant; + o->type = e->type; + + return Expr_Expr; + case_end; + case_ast_node(ie, IndexExpr, node); check_expr(c, o, ie->expr); if (o->mode == Addressing_Invalid) { @@ -6832,6 +6872,11 @@ gbString write_expr_to_string(gbString str, Ast *node) { str = write_expr_to_string(str, se->selector); case_end; + case_ast_node(se, ImplicitSelectorExpr, node); + str = gb_string_append_rune(str, '.'); + str = write_expr_to_string(str, se->selector); + case_end; + case_ast_node(ta, TypeAssertion, node); str = write_expr_to_string(str, ta->expr); str = gb_string_appendc(str, ".("); diff --git a/src/ir.cpp b/src/ir.cpp index e3fe83c3b..0d5e3fc36 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -6268,6 +6268,13 @@ irValue *ir_build_expr_internal(irProcedure *proc, Ast *expr) { return ir_addr_load(proc, ir_build_addr(proc, expr)); case_end; + case_ast_node(ise, ImplicitSelectorExpr, expr); + TypeAndValue tav = type_and_value_of_expr(expr); + GB_ASSERT(tav.mode == Addressing_Constant); + + return ir_add_module_constant(proc->module, tv.type, tv.value); + case_end; + case_ast_node(te, TernaryExpr, expr); ir_emit_comment(proc, str_lit("TernaryExpr")); diff --git a/src/parser.cpp b/src/parser.cpp index a5526fd73..84c03587d 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -25,6 +25,11 @@ Token ast_token(Ast *node) { return ast_token(node->SelectorExpr.selector); } return node->SelectorExpr.token; + case Ast_ImplicitSelectorExpr: + if (node->ImplicitSelectorExpr.selector != nullptr) { + return ast_token(node->ImplicitSelectorExpr.selector); + } + return node->ImplicitSelectorExpr.token; case Ast_IndexExpr: return node->IndexExpr.open; case Ast_SliceExpr: return node->SliceExpr.open; case Ast_Ellipsis: return node->Ellipsis.token; @@ -165,6 +170,9 @@ Ast *clone_ast(Ast *node) { n->SelectorExpr.expr = clone_ast(n->SelectorExpr.expr); n->SelectorExpr.selector = clone_ast(n->SelectorExpr.selector); break; + case Ast_ImplicitSelectorExpr: + n->ImplicitSelectorExpr.selector = clone_ast(n->ImplicitSelectorExpr.selector); + break; case Ast_IndexExpr: n->IndexExpr.expr = clone_ast(n->IndexExpr.expr); n->IndexExpr.index = clone_ast(n->IndexExpr.index); @@ -504,11 +512,20 @@ Ast *ast_call_expr(AstFile *f, Ast *proc, Array args, Token open, Token c Ast *ast_selector_expr(AstFile *f, Token token, Ast *expr, Ast *selector) { Ast *result = alloc_ast_node(f, Ast_SelectorExpr); + result->SelectorExpr.token = token; result->SelectorExpr.expr = expr; result->SelectorExpr.selector = selector; return result; } +Ast *ast_implicit_selector_expr(AstFile *f, Token token, Ast *selector) { + Ast *result = alloc_ast_node(f, Ast_ImplicitSelectorExpr); + result->ImplicitSelectorExpr.token = token; + result->ImplicitSelectorExpr.selector = selector; + return result; +} + + Ast *ast_index_expr(AstFile *f, Ast *expr, Ast *index, Token open, Token close) { Ast *result = alloc_ast_node(f, Ast_IndexExpr); result->IndexExpr.expr = expr; @@ -1612,7 +1629,6 @@ Ast *parse_operand(AstFile *f, bool lhs) { case Token_offset_of: return parse_call_expr(f, ast_implicit(f, advance_token(f))); - case Token_String: return ast_basic_lit(f, advance_token(f)); @@ -2277,6 +2293,12 @@ Ast *parse_unary_expr(AstFile *f, bool lhs) { Ast *expr = parse_unary_expr(f, lhs); return ast_unary_expr(f, token, expr); } + + case Token_Period: { + Token token = expect_token(f, Token_Period); + Ast *ident = parse_ident(f); + return ast_implicit_selector_expr(f, token, ident); + } } return parse_atom_expr(f, parse_operand(f, lhs), lhs); diff --git a/src/parser.hpp b/src/parser.hpp index d685aa1af..816f3f534 100644 --- a/src/parser.hpp +++ b/src/parser.hpp @@ -245,6 +245,7 @@ AST_KIND(_ExprBegin, "", bool) \ AST_KIND(BinaryExpr, "binary expression", struct { Token op; Ast *left, *right; } ) \ AST_KIND(ParenExpr, "parentheses expression", struct { Ast *expr; Token open, close; }) \ AST_KIND(SelectorExpr, "selector expression", struct { Token token; Ast *expr, *selector; }) \ + AST_KIND(ImplicitSelectorExpr, "implicit selector expression", struct { Token token; Ast *selector; }) \ AST_KIND(IndexExpr, "index expression", struct { Ast *expr, *index; Token open, close; }) \ AST_KIND(DerefExpr, "dereference expression", struct { Token op; Ast *expr; }) \ AST_KIND(SliceExpr, "slice expression", struct { \ -- cgit v1.2.3 From c67ea9784560d3e56febe8acd6270d4cfa6daa50 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 6 Mar 2019 19:08:37 +0000 Subject: Add implicit selector expressions for in/notin --- core/mem/allocators.odin | 28 ++++++++++++---------------- core/strconv/strconv.odin | 6 +++--- src/check_expr.cpp | 14 +++++++++++++- 3 files changed, 28 insertions(+), 20 deletions(-) (limited to 'src/check_expr.cpp') diff --git a/core/mem/allocators.odin b/core/mem/allocators.odin index 6dafe18c0..77cc0abf1 100644 --- a/core/mem/allocators.odin +++ b/core/mem/allocators.odin @@ -47,12 +47,10 @@ arena_allocator :: proc(arena: ^Arena) -> Allocator { arena_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, size, alignment: int, old_memory: rawptr, old_size: int, flags: u64, location := #caller_location) -> rawptr { - using Allocator_Mode; arena := cast(^Arena)allocator_data; - switch mode { - case Alloc: + case .Alloc: total_size := size + alignment; if arena.offset + total_size > len(arena.data) { @@ -66,14 +64,14 @@ arena_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, arena.peak_used = max(arena.peak_used, arena.offset); return zero(ptr, size); - case Free: + case .Free: // NOTE(bill): Free all at once // Use Arena_Temp_Memory if you want to free a block - case Free_All: + case .Free_All: arena.offset = 0; - case Resize: + case .Resize: return default_resize_align(old_memory, old_size, size, alignment, arena_allocator(arena)); } @@ -227,7 +225,6 @@ stack_allocator :: proc(stack: ^Stack) -> Allocator { stack_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, size, alignment: int, old_memory: rawptr, old_size: int, flags: u64, location := #caller_location) -> rawptr { - using Allocator_Mode; s := cast(^Stack)allocator_data; if s.data == nil { @@ -256,9 +253,9 @@ stack_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, } switch mode { - case Alloc: + case .Alloc: return raw_alloc(s, size, alignment); - case Free: + case .Free: if old_memory == nil { return nil; } @@ -288,11 +285,11 @@ stack_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, s.prev_offset = int(header.prev_offset); - case Free_All: + case .Free_All: s.prev_offset = 0; s.curr_offset = 0; - case Resize: + case .Resize: if old_memory == nil { return raw_alloc(s, size, alignment); } @@ -374,7 +371,6 @@ small_stack_allocator :: proc(stack: ^Small_Stack) -> Allocator { small_stack_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, size, alignment: int, old_memory: rawptr, old_size: int, flags: u64, location := #caller_location) -> rawptr { - using Allocator_Mode; s := cast(^Small_Stack)allocator_data; if s.data == nil { @@ -403,9 +399,9 @@ small_stack_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, } switch mode { - case Alloc: + case .Alloc: return raw_alloc(s, size, alignment); - case Free: + case .Free: if old_memory == nil { return nil; } @@ -428,10 +424,10 @@ small_stack_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, s.offset = int(old_offset); - case Free_All: + case .Free_All: s.offset = 0; - case Resize: + case .Resize: if old_memory == nil { return raw_alloc(s, size, alignment); } diff --git a/core/strconv/strconv.odin b/core/strconv/strconv.odin index 0526a65ba..d509d7b6a 100644 --- a/core/strconv/strconv.odin +++ b/core/strconv/strconv.odin @@ -475,7 +475,7 @@ append_bits :: proc(buf: []byte, u: u64, base: int, is_signed: bool, bit_size: i } i-=1; a[i] = digits[u % b]; - if Int_Flag.Prefix in flags { + if .Prefix in flags { ok := true; switch base { case 2: i-=1; a[i] = 'b'; @@ -493,9 +493,9 @@ append_bits :: proc(buf: []byte, u: u64, base: int, is_signed: bool, bit_size: i switch { case neg: i-=1; a[i] = '-'; - case Int_Flag.Plus in flags: + case .Plus in flags: i-=1; a[i] = '+'; - case Int_Flag.Space in flags: + case .Space in flags: i-=1; a[i] = ' '; } diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 4c921f484..532b79969 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -2144,8 +2144,20 @@ void check_binary_expr(CheckerContext *c, Operand *x, Ast *node, bool use_lhs_as case Token_in: case Token_notin: - check_expr(c, x, be->left); + // IMPORTANT NOTE(bill): This uses right-left evaluation in type checking only no in + check_expr(c, y, be->right); + + if (is_type_bit_set(y->type)) { + Type *elem = base_type(y->type)->BitSet.elem; + check_expr_with_type_hint(c, x, be->left, elem); + } else if (is_type_map(y->type)) { + Type *key = base_type(y->type)->Map.key; + check_expr_with_type_hint(c, x, be->left, key); + } else { + check_expr(c, x, be->left); + } + if (x->mode == Addressing_Invalid) { return; } -- cgit v1.2.3 From 5c04800831d4b6b642d40e2866b88661cd8ac31e Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 6 Mar 2019 20:01:46 +0000 Subject: Add type inference to index expressions for maps --- src/check_expr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/check_expr.cpp') diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 532b79969..f533a1812 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -6473,7 +6473,7 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type if (is_type_map(t)) { Operand key = {}; - check_expr(c, &key, ie->index); + check_expr_with_type_hint(c, &key, ie->index, t->Map.key); check_assignment(c, &key, t->Map.key, str_lit("map index")); if (key.mode == Addressing_Invalid) { o->mode = Addressing_Invalid; -- 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_expr.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