From 1f2f3cb315d7ffea69321712f6431b0230c98f62 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 26 Aug 2020 22:40:03 +0100 Subject: [PATCH 1/5] Fix #712 --- core/time/time.odin | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/core/time/time.odin b/core/time/time.odin index 46f18f89a..51aeb380b 100644 --- a/core/time/time.odin +++ b/core/time/time.odin @@ -146,6 +146,7 @@ WALL_TO_INTERNAL :: i64((1884*365 + 1884/4 - 1884/100 + 1884/400) * SECONDS_PER_ INTERNAL_TO_WALL :: i64(- WALL_TO_INTERNAL); UNIX_TO_ABSOLUTE :: i64(UNIX_TO_INTERNAL + INTERNAL_TO_ABSOLUTE); +ABSOLUTE_TO_UNIX :: i64(-UNIX_TO_ABSOLUTE); _is_leap_year :: proc(year: int) -> bool { return year%4 == 0 && (year%100 != 0 || year%400 == 0); @@ -192,11 +193,12 @@ _abs_date :: proc(abs: u64, full: bool) -> (year: int, month: Month, day: int, y } day = yday; + if _is_leap_year(year) do switch { - case day < 31+29-1: + case day > 31+29-1: day -= 1; case day == 31+29-1: - month = Month.February; + month = .February; day = 29; return; } From df3690c32a4e988bcce5e3b5d6b338a801ed1518 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 26 Aug 2020 22:46:54 +0100 Subject: [PATCH 2/5] Revert accidental removal of `#const` for procedure variable parameters #718 --- src/check_type.cpp | 11 +++++++++++ src/parser.cpp | 4 ++++ src/parser.hpp | 3 ++- 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/check_type.cpp b/src/check_type.cpp index fe76d65d5..32309ce26 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -1662,6 +1662,10 @@ Type *check_get_params(CheckerContext *ctx, Scope *scope, Ast *_params, bool *is error(name, "'auto_cast' can only be applied to variable fields"); p->flags &= ~FieldFlag_auto_cast; } + if (p->flags&FieldFlag_const) { + error(name, "'#const' can only be applied to variable fields"); + p->flags &= ~FieldFlag_const; + } param = alloc_entity_type_name(scope, name->Ident.token, type, EntityState_Resolved); param->TypeName.is_type_alias = true; @@ -1726,6 +1730,10 @@ Type *check_get_params(CheckerContext *ctx, Scope *scope, Ast *_params, bool *is error(name, "'auto_cast' can only be applied to variable fields"); p->flags &= ~FieldFlag_auto_cast; } + if (p->flags&FieldFlag_const) { + error(name, "'#const' can only be applied to variable fields"); + p->flags &= ~FieldFlag_const; + } if (!is_type_constant_type(type) && !is_type_polymorphic(type)) { gbString str = type_to_string(type); @@ -1745,6 +1753,9 @@ Type *check_get_params(CheckerContext *ctx, Scope *scope, Ast *_params, bool *is if (p->flags&FieldFlag_auto_cast) { param->flags |= EntityFlag_AutoCast; } + if (p->flags&FieldFlag_const) { + param->flags |= EntityFlag_ConstInput; + } param->state = EntityState_Resolved; // NOTE(bill): This should have be resolved whilst determining it add_entity(ctx->checker, scope, name, param); diff --git a/src/parser.cpp b/src/parser.cpp index 7d794a898..702ef6605 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -3127,6 +3127,7 @@ u32 parse_field_prefixes(AstFile *f) { i32 no_alias_count = 0; i32 c_vararg_count = 0; i32 auto_cast_count = 0; + i32 const_count = 0; for (;;) { FieldPrefixKind kind = is_token_field_prefix(f); @@ -3144,12 +3145,14 @@ u32 parse_field_prefixes(AstFile *f) { case FieldPrefix_no_alias: no_alias_count += 1; advance_token(f); break; case FieldPrefix_c_var_arg: c_vararg_count += 1; advance_token(f); break; case FieldPrefix_auto_cast: auto_cast_count += 1; advance_token(f); break; + case FieldPrefix_const: const_count += 1; advance_token(f); break; } } if (using_count > 1) syntax_error(f->curr_token, "Multiple 'using' in this field list"); if (no_alias_count > 1) syntax_error(f->curr_token, "Multiple '#no_alias' in this field list"); if (c_vararg_count > 1) syntax_error(f->curr_token, "Multiple '#c_vararg' in this field list"); if (auto_cast_count > 1) syntax_error(f->curr_token, "Multiple 'auto_cast' in this field list"); + if (const_count > 1) syntax_error(f->curr_token, "Multiple '#const' in this field list"); u32 field_flags = 0; @@ -3157,6 +3160,7 @@ u32 parse_field_prefixes(AstFile *f) { if (no_alias_count > 0) field_flags |= FieldFlag_no_alias; if (c_vararg_count > 0) field_flags |= FieldFlag_c_vararg; if (auto_cast_count > 0) field_flags |= FieldFlag_auto_cast; + if (const_count > 0) field_flags |= FieldFlag_const; return field_flags; } diff --git a/src/parser.hpp b/src/parser.hpp index 76ba5c04f..a98060df9 100644 --- a/src/parser.hpp +++ b/src/parser.hpp @@ -212,12 +212,13 @@ enum FieldFlag { FieldFlag_no_alias = 1<<2, FieldFlag_c_vararg = 1<<3, FieldFlag_auto_cast = 1<<4, + FieldFlag_const = 1<<5, FieldFlag_Tags = 1<<10, FieldFlag_Results = 1<<16, - FieldFlag_Signature = FieldFlag_ellipsis|FieldFlag_using|FieldFlag_no_alias|FieldFlag_c_vararg|FieldFlag_auto_cast, + FieldFlag_Signature = FieldFlag_ellipsis|FieldFlag_using|FieldFlag_no_alias|FieldFlag_c_vararg|FieldFlag_auto_cast|FieldFlag_const, FieldFlag_Struct = FieldFlag_using|FieldFlag_Tags, }; From d3eca21e40ded7dfc15a4f56b2eaaceffa55ccbe Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 26 Aug 2020 22:48:32 +0100 Subject: [PATCH 3/5] Fix style in parse.odin --- core/odin/parser/parser.odin | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/core/odin/parser/parser.odin b/core/odin/parser/parser.odin index 38e97d51f..925aa1f0c 100644 --- a/core/odin/parser/parser.odin +++ b/core/odin/parser/parser.odin @@ -1654,13 +1654,10 @@ parse_field_list :: proc(p: ^Parser, follow: tokenizer.Token_Kind, allowed_flags names := make([]^ast.Expr, 1); names[0] = ast.new(ast.Ident, tok.pos, end_pos(tok)); switch ident in &names[0].derived { - case ast.Ident: { - ident.name = tok.text; - } - - case: { - unreachable(); - } + case ast.Ident: + ident.name = tok.text; + case: + unreachable(); } flags := check_field_flag_prefixes(p, len(list), allowed_flags, eaf.flags); From c783840eab1a7b1d89467e631ff26391e1023e7e Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 26 Aug 2020 23:20:25 +0100 Subject: [PATCH 4/5] Fix #642 --- src/ir.cpp | 28 ++++++++++++++++++++++++++++ src/llvm_backend.cpp | 32 +++++++++++++++++++++++++++++++- 2 files changed, 59 insertions(+), 1 deletion(-) diff --git a/src/ir.cpp b/src/ir.cpp index 2b3b3e14f..77d40dc52 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -4227,6 +4227,28 @@ irValue *ir_addr_get_ptr(irProcedure *proc, irAddr const &addr, bool allow_refer } } + case irAddr_RelativePointer: { + Type *rel_ptr = base_type(ir_addr_type(addr)); + GB_ASSERT(rel_ptr->kind == Type_RelativePointer); + + irValue *ptr = ir_emit_conv(proc, addr.addr, t_uintptr); + irValue *offset = ir_emit_conv(proc, ptr, alloc_type_pointer(rel_ptr->RelativePointer.base_integer)); + offset = ir_emit_load(proc, offset); + + if (!is_type_unsigned(rel_ptr->RelativePointer.base_integer)) { + offset = ir_emit_conv(proc, offset, t_i64); + } + offset = ir_emit_conv(proc, offset, t_uintptr); + irValue *absolute_ptr = ir_emit_arith(proc, Token_Add, ptr, offset, t_uintptr); + absolute_ptr = ir_emit_conv(proc, absolute_ptr, rel_ptr->RelativePointer.pointer_type); + + irValue *cond = ir_emit_comp(proc, Token_CmpEq, offset, ir_value_nil(rel_ptr->RelativePointer.base_integer)); + + // NOTE(bill): nil check + irValue *nil_ptr = ir_value_nil(rel_ptr->RelativePointer.pointer_type); + irValue *final_ptr = ir_emit_select(proc, cond, nil_ptr, absolute_ptr); + return final_ptr; + } case irAddr_BitField: { irValue *v = ir_addr_load(proc, addr); @@ -5101,6 +5123,10 @@ irValue *ir_emit_struct_ep(irProcedure *proc, irValue *s, i32 index) { t = t->Opaque.elem; } + if (is_type_relative_pointer(t)) { + s = ir_addr_get_ptr(proc, ir_addr(s)); + } + if (is_type_struct(t)) { result_type = alloc_type_pointer(t->Struct.fields[index]->type); } else if (is_type_union(t)) { @@ -5337,6 +5363,8 @@ irValue *ir_emit_deep_field_gep(irProcedure *proc, irValue *e, Selection sel) { e = ir_emit_array_epi(proc, e, index); } else if (type->kind == Type_Map) { e = ir_emit_struct_ep(proc, e, index); + } else if (type->kind == Type_RelativePointer) { + e = ir_emit_struct_ep(proc, e, index); } else { GB_PANIC("un-gep-able type %s", type_to_string(type)); } diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 5ba641897..d5b2d9f8d 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -145,6 +145,30 @@ lbValue lb_addr_get_ptr(lbProcedure *p, lbAddr const &addr) { return lb_emit_conv(p, ptr, alloc_type_pointer(map_type->Map.value)); } + + case lbAddr_RelativePointer: { + Type *rel_ptr = base_type(lb_addr_type(addr)); + GB_ASSERT(rel_ptr->kind == Type_RelativePointer); + + lbValue ptr = lb_emit_conv(p, addr.addr, t_uintptr); + lbValue offset = lb_emit_conv(p, ptr, alloc_type_pointer(rel_ptr->RelativePointer.base_integer)); + offset = lb_emit_load(p, offset); + + if (!is_type_unsigned(rel_ptr->RelativePointer.base_integer)) { + offset = lb_emit_conv(p, offset, t_i64); + } + offset = lb_emit_conv(p, offset, t_uintptr); + lbValue absolute_ptr = lb_emit_arith(p, Token_Add, ptr, offset, t_uintptr); + absolute_ptr = lb_emit_conv(p, absolute_ptr, rel_ptr->RelativePointer.pointer_type); + + lbValue cond = lb_emit_comp(p, Token_CmpEq, offset, lb_const_nil(p->module, rel_ptr->RelativePointer.base_integer)); + + // NOTE(bill): nil check + lbValue nil_ptr = lb_const_nil(p->module, rel_ptr->RelativePointer.pointer_type); + lbValue final_ptr = lb_emit_select(p, cond, nil_ptr, absolute_ptr); + return final_ptr; + } + case lbAddr_BitField: { lbValue v = lb_addr_load(p, addr); return lb_address_from_load_or_generate_local(p, v); @@ -6562,6 +6586,10 @@ lbValue lb_emit_struct_ep(lbProcedure *p, lbValue s, i32 index) { t = t->Opaque.elem; } + if (is_type_relative_pointer(t)) { + s = lb_addr_get_ptr(p, lb_addr(s)); + } + if (is_type_struct(t)) { result_type = get_struct_field_type(t, index); } else if (is_type_union(t)) { @@ -6809,7 +6837,7 @@ lbValue lb_emit_deep_field_gep(lbProcedure *p, lbValue e, Selection sel) { break; default: - GB_PANIC("un-gep-able type"); + GB_PANIC("un-gep-able type %s", type_to_string(type)); break; } } else if (type->kind == Type_Slice) { @@ -6820,6 +6848,8 @@ lbValue lb_emit_deep_field_gep(lbProcedure *p, lbValue e, Selection sel) { e = lb_emit_array_epi(p, e, index); } else if (type->kind == Type_Map) { e = lb_emit_struct_ep(p, e, index); + } else if (type->kind == Type_RelativePointer) { + e = lb_emit_struct_ep(p, e, index); } else { GB_PANIC("un-gep-able type %s", type_to_string(type)); } From d31c63c0ae76115d1b9aa8b5d1f8bf7130e74977 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 27 Aug 2020 00:11:02 +0100 Subject: [PATCH 5/5] Fix #714 --- src/check_type.cpp | 2 +- src/types.cpp | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/check_type.cpp b/src/check_type.cpp index 32309ce26..7be70c11d 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -1137,7 +1137,7 @@ void check_bit_set_type(CheckerContext *c, Type *type, Type *named_type, Ast *no } else { Type *elem = check_type_expr(c, bs->elem, nullptr); - #if 1 + #if 0 if (named_type != nullptr && named_type->kind == Type_Named && elem->kind == Type_Enum) { // NOTE(bill): Anonymous enumeration diff --git a/src/types.cpp b/src/types.cpp index 4372bdd6a..453540252 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -877,6 +877,9 @@ Type *alloc_type_named(String name, Type *base, Entity *type_name) { Type *t = alloc_type(Type_Named); t->Named.name = name; t->Named.base = base; + if (base != t) { + t->Named.base = base_type(base); + } t->Named.type_name = type_name; return t; }