diff options
| author | Jeroen van Rijn <Kelimion@users.noreply.github.com> | 2021-06-27 16:50:27 +0200 |
|---|---|---|
| committer | Jeroen van Rijn <Kelimion@users.noreply.github.com> | 2021-06-27 16:50:27 +0200 |
| commit | 6836b501afdedb8fec583400ee86d379938434bc (patch) | |
| tree | 3dfeedfaa2cf71e340f4d0a2e46d8fb3e257a4bd /src | |
| parent | d949d5a046297b3aa08da03bb65cc13c2d5528ac (diff) | |
| parent | 76d3bab955d33abb6d4cab0b95beedd6393c96da (diff) | |
Merge branch 'master' into zlib_optimize
Diffstat (limited to 'src')
| -rw-r--r-- | src/check_builtin.cpp | 60 | ||||
| -rw-r--r-- | src/checker_builtin_procs.hpp | 2 | ||||
| -rw-r--r-- | src/llvm_backend.cpp | 47 | ||||
| -rw-r--r-- | src/tokenizer.cpp | 10 |
4 files changed, 95 insertions, 24 deletions
diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index f08a33fde..378779dc6 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -445,38 +445,77 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 case BuiltinProc_offset_of: { + // offset_of :: proc(value.field) -> uintptr // offset_of :: proc(Type, field) -> uintptr - Operand op = {}; - Type *bt = check_type(c, ce->args[0]); - Type *type = base_type(bt); - if (type == nullptr || type == t_invalid) { - error(ce->args[0], "Expected a type for 'offset_of'"); + + Type *type = nullptr; + Ast *field_arg = nullptr; + + if (ce->args.count == 1) { + Ast *arg0 = unparen_expr(ce->args[0]); + if (arg0->kind != Ast_SelectorExpr) { + gbString x = expr_to_string(arg0); + error(ce->args[0], "Invalid expression for 'offset_of', '%s' is not a selector expression", x); + gb_string_free(x); + return false; + } + + ast_node(se, SelectorExpr, arg0); + + Operand x = {}; + check_expr(c, &x, se->expr); + if (x.mode == Addressing_Invalid) { + return false; + } + type = type_deref(x.type); + + Type *bt = base_type(type); + if (bt == nullptr || bt == t_invalid) { + error(ce->args[0], "Expected a type for 'offset_of'"); + return false; + } + + field_arg = unparen_expr(se->selector); + } else if (ce->args.count == 2) { + type = check_type(c, ce->args[0]); + Type *bt = base_type(type); + if (bt == nullptr || bt == t_invalid) { + error(ce->args[0], "Expected a type for 'offset_of'"); + return false; + } + + field_arg = unparen_expr(ce->args[1]); + } else { + error(ce->args[0], "Expected either 1 or 2 arguments to 'offset_of', in the format of 'offset_of(Type, field)', 'offset_of(value.field)'"); return false; } + GB_ASSERT(type != nullptr); - Ast *field_arg = unparen_expr(ce->args[1]); if (field_arg == nullptr || field_arg->kind != Ast_Ident) { error(field_arg, "Expected an identifier for field argument"); return false; } if (is_type_array(type)) { - error(field_arg, "Invalid type for 'offset_of'"); + gbString t = type_to_string(type); + error(field_arg, "Invalid a struct type for 'offset_of', got '%s'", t); + gb_string_free(t); return false; } ast_node(arg, Ident, field_arg); - Selection sel = lookup_field(type, arg->token.string, operand->mode == Addressing_Type); + String field_name = arg->token.string; + Selection sel = lookup_field(type, field_name, false); if (sel.entity == nullptr) { - gbString type_str = type_to_string(bt); + gbString type_str = type_to_string(type); error(ce->args[0], "'%s' has no field named '%.*s'", type_str, LIT(arg->token.string)); gb_string_free(type_str); return false; } if (sel.indirect) { - gbString type_str = type_to_string(bt); + gbString type_str = type_to_string(type); error(ce->args[0], "Field '%.*s' is embedded via a pointer in '%s'", LIT(arg->token.string), type_str); gb_string_free(type_str); @@ -486,7 +525,6 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 operand->mode = Addressing_Constant; operand->value = exact_value_i64(type_offset_of_from_selection(type, sel)); operand->type = t_uintptr; - break; } diff --git a/src/checker_builtin_procs.hpp b/src/checker_builtin_procs.hpp index aa93fbacd..57b5d7eb9 100644 --- a/src/checker_builtin_procs.hpp +++ b/src/checker_builtin_procs.hpp @@ -238,7 +238,7 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = { {STR_LIT("size_of"), 1, false, Expr_Expr, BuiltinProcPkg_builtin}, {STR_LIT("align_of"), 1, false, Expr_Expr, BuiltinProcPkg_builtin}, - {STR_LIT("offset_of"), 2, false, Expr_Expr, BuiltinProcPkg_builtin}, + {STR_LIT("offset_of"), 1, true, Expr_Expr, BuiltinProcPkg_builtin}, {STR_LIT("type_of"), 1, false, Expr_Expr, BuiltinProcPkg_builtin}, {STR_LIT("type_info_of"), 1, false, Expr_Expr, BuiltinProcPkg_builtin}, {STR_LIT("typeid_of"), 1, false, Expr_Expr, BuiltinProcPkg_builtin}, diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index a9a9ad0ac..47ff21ee8 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -2132,6 +2132,28 @@ LLVMMetadataRef lb_debug_type_internal(lbModule *m, Type *type) { return nullptr; } +LLVMMetadataRef lb_get_base_scope_metadata(lbModule *m, Scope *scope) { + LLVMMetadataRef found = nullptr; + for (;;) { + if (scope == nullptr) { + return nullptr; + } + if (scope->flags & ScopeFlag_Proc) { + found = lb_get_llvm_metadata(m, scope->procedure_entity); + if (found) { + return found; + } + } + if (scope->flags & ScopeFlag_File) { + found = lb_get_llvm_metadata(m, scope->file); + if (found) { + return found; + } + } + scope = scope->parent; + } +} + LLVMMetadataRef lb_debug_type(lbModule *m, Type *type) { GB_ASSERT(type != nullptr); LLVMMetadataRef found = lb_get_llvm_metadata(m, type); @@ -2147,7 +2169,7 @@ LLVMMetadataRef lb_debug_type(lbModule *m, Type *type) { if (type->Named.type_name != nullptr) { Entity *e = type->Named.type_name; - scope = lb_get_llvm_metadata(m, e->scope); + scope = lb_get_base_scope_metadata(m, e->scope); if (scope != nullptr) { file = LLVMDIScopeGetFile(scope); } @@ -2174,8 +2196,6 @@ LLVMMetadataRef lb_debug_type(lbModule *m, Type *type) { switch (bt->kind) { case Type_Enum: { - LLVMMetadataRef scope = nullptr; - LLVMMetadataRef file = nullptr; unsigned line = 0; unsigned element_count = cast(unsigned)bt->Enum.fields.count; LLVMMetadataRef *elements = gb_alloc_array(permanent_allocator(), LLVMMetadataRef, element_count); @@ -13460,7 +13480,6 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) { default: GB_PANIC("Unknown CompoundLit type: %s", type_to_string(type)); break; case Type_Struct: { - // TODO(bill): "constant" '#raw_union's are not initialized constantly at the moment. // NOTE(bill): This is due to the layout of the unions when printed to LLVM-IR bool is_raw_union = is_type_raw_union(bt); @@ -15048,9 +15067,23 @@ lbProcedure *lb_create_startup_runtime(lbModule *main_module, lbProcedure *start GB_ASSERT(e->kind == Entity_Variable); e->code_gen_module = entity_module; - if (var->decl->init_expr != nullptr) { - // gb_printf_err("%s\n", expr_to_string(var->decl->init_expr)); - lbValue init = lb_build_expr(p, var->decl->init_expr); + Ast *init_expr = var->decl->init_expr; + if (init_expr != nullptr) { + lbValue init = lb_build_expr(p, init_expr); + if (init.value == nullptr) { + LLVMTypeRef global_type = LLVMGetElementType(LLVMTypeOf(var->var.value)); + if (is_type_untyped_undef(init.type)) { + LLVMSetInitializer(var->var.value, LLVMGetUndef(global_type)); + var->is_initialized = true; + continue; + } else if (is_type_untyped_nil(init.type)) { + LLVMSetInitializer(var->var.value, LLVMConstNull(global_type)); + var->is_initialized = true; + continue; + } + GB_PANIC("Invalid init value, got %s", expr_to_string(init_expr)); + } + LLVMValueKind value_kind = LLVMGetValueKind(init.value); // gb_printf_err("%s %d\n", LLVMPrintValueToString(init.value)); diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp index 826fccc04..edffb7446 100644 --- a/src/tokenizer.cpp +++ b/src/tokenizer.cpp @@ -1409,14 +1409,14 @@ void tokenizer_get_token(Tokenizer *t, Token *token, int repeat=0) { if (t->curr_rune == '=') { advance_to_next_rune(t); token->kind = Token_SubEq; - } else if (t->curr_rune == '-' && peek_byte(t) == '-') { - advance_to_next_rune(t); - advance_to_next_rune(t); - token->kind = Token_Undef; } else if (t->curr_rune == '-') { + insert_semicolon = true; advance_to_next_rune(t); token->kind = Token_Decrement; - insert_semicolon = true; + if (t->curr_rune == '-') { + advance_to_next_rune(t); + token->kind = Token_Undef; + } } else if (t->curr_rune == '>') { advance_to_next_rune(t); token->kind = Token_ArrowRight; |