diff options
| author | gingerBill <bill@gingerbill.org> | 2020-05-15 17:37:00 +0100 |
|---|---|---|
| committer | gingerBill <bill@gingerbill.org> | 2020-05-15 17:37:00 +0100 |
| commit | ff92eb911271fd9ad3b7c4261897fcf20899918c (patch) | |
| tree | 29f98d87c03b1a32cb96875e916959b3009e8f66 /src/check_type.cpp | |
| parent | 8b066b24563a7b2644c1128d267d90f16c7b5a73 (diff) | |
Relative pointers
Diffstat (limited to 'src/check_type.cpp')
| -rw-r--r-- | src/check_type.cpp | 44 |
1 files changed, 42 insertions, 2 deletions
diff --git a/src/check_type.cpp b/src/check_type.cpp index 8aa24a752..3829694a0 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -329,7 +329,7 @@ void add_polymorphic_record_entity(CheckerContext *ctx, Ast *node, Type *named_t auto *found_gen_types = map_get(&ctx->checker->info.gen_types, hash_pointer(original_type)); if (found_gen_types) { - array_add(found_gen_types, e); + array_add(found_gen_types, e); } else { auto array = array_make<Entity *>(heap_allocator()); array_add(&array, e); @@ -2501,7 +2501,7 @@ bool check_procedure_type(CheckerContext *ctx, Type *type, Ast *proc_type_node, c->curr_proc_sig = type; c->in_proc_sig = true; - + ProcCallingConvention cc = pt->calling_convention; if (cc == ProcCC_ForeignBlockDefault) { cc = ProcCC_CDecl; @@ -3284,6 +3284,46 @@ bool check_type_internal(CheckerContext *ctx, Ast *e, Type **type, Type *named_t return true; case_end; + case_ast_node(rt, RelativeType, e); + GB_ASSERT(rt->tag->kind == Ast_CallExpr); + ast_node(ce, CallExpr, rt->tag); + + Type *base_integer = nullptr; + + if (ce->args.count != 1) { + error(rt->type, "#relative expected 1 type argument, got %td", ce->args.count); + } else { + base_integer = check_type(ctx, ce->args[0]); + if (!is_type_integer(base_integer)) { + error(rt->type, "#relative base types must be an integer"); + base_integer = nullptr; + } else if (type_size_of(base_integer) > 64) { + error(rt->type, "#relative base integer types be less than or equal to 64-bits"); + base_integer = nullptr; + } + } + + Type *relative_type = nullptr; + Type *base_type = check_type(ctx, rt->type); + if (!is_type_pointer(base_type) && !is_type_slice(base_type)) { + error(rt->type, "#relative types can only be a pointer or slice"); + relative_type = base_type; + } else if (base_integer == nullptr) { + relative_type = base_type; + } else { + if (is_type_pointer(base_type)) { + relative_type = alloc_type_relative_pointer(base_type, base_integer); + } else if (is_type_slice(base_type)) { + relative_type = alloc_type_relative_slice(base_type, base_integer); + } + } + GB_ASSERT(relative_type != nullptr); + + *type = relative_type; + set_base_type(named_type, *type); + return true; + case_end; + case_ast_node(ot, OpaqueType, e); Type *elem = strip_opaque_type(check_type_expr(ctx, ot->type, nullptr)); *type = alloc_type_opaque(elem); |