diff options
| author | gingerBill <bill@gingerbill.org> | 2020-03-15 14:31:26 +0000 |
|---|---|---|
| committer | gingerBill <bill@gingerbill.org> | 2020-03-15 14:31:26 +0000 |
| commit | 18fb6a4be41f30de75b445266b958e153ecc16d9 (patch) | |
| tree | 6770795d754effc1751d8c7beb13652db39f3770 /src | |
| parent | bf0c6f5a30e406a0e0f73014c024ba63dcb47b43 (diff) | |
| parent | 8dba0e332c73a08301c5ac6c0d310c483c66cb11 (diff) | |
Merge branch 'master' into llvm-integration
Diffstat (limited to 'src')
| -rw-r--r-- | src/build_settings.cpp | 6 | ||||
| -rw-r--r-- | src/check_decl.cpp | 5 | ||||
| -rw-r--r-- | src/check_stmt.cpp | 4 | ||||
| -rw-r--r-- | src/check_type.cpp | 7 | ||||
| -rw-r--r-- | src/checker.cpp | 22 | ||||
| -rw-r--r-- | src/checker.hpp | 3 | ||||
| -rw-r--r-- | src/entity.cpp | 13 | ||||
| -rw-r--r-- | src/ir.cpp | 35 | ||||
| -rw-r--r-- | src/ir_print.cpp | 30 |
9 files changed, 106 insertions, 19 deletions
diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 9d2453929..8cb40cadc 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -656,7 +656,6 @@ void init_build_context(TargetMetrics *cross_target) { gb_exit(1); } - bc->llc_flags = make_string_c(llc_flags); bc->optimization_level = gb_clamp(bc->optimization_level, 0, 3); @@ -669,9 +668,12 @@ void init_build_context(TargetMetrics *cross_target) { // -memcpyopt: MemCpy optimization } if (bc->ODIN_DEBUG == false) { - opt_flags = gb_string_appendc(opt_flags, "-memcpyopt -die "); + opt_flags = gb_string_appendc(opt_flags, "-mem2reg -memcpyopt -die "); } + bc->llc_flags = make_string_c(llc_flags); + + // NOTE(lachsinc): This optimization option was previously required to get // around an issue in fmt.odin. Thank bp for tracking it down! Leaving for now until the issue // is resolved and confirmed by Bill. Maybe it should be readded in non-debug builds. diff --git a/src/check_decl.cpp b/src/check_decl.cpp index 8a231fe36..13f05c5b5 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -844,6 +844,11 @@ void check_global_variable_decl(CheckerContext *ctx, Entity *e, Ast *type_expr, check_decl_attributes(ctx, decl->attributes, var_decl_attribute, &ac); } + if (ac.require_declaration) { + array_add(&ctx->info->required_global_variables, e); + } + + e->Variable.thread_local_model = ac.thread_local_model; e->Variable.is_export = ac.is_export; if (ac.is_static) { diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index 4b250c6a6..67172d951 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -1692,12 +1692,12 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) { switch (token.kind) { case Token_break: if ((flags & Stmt_BreakAllowed) == 0 && bs->label == nullptr) { - error(token, "'break' only allowed in loops or 'switch' statements"); + error(token, "'break' only allowed in non-inline loops or 'switch' statements"); } break; case Token_continue: if ((flags & Stmt_ContinueAllowed) == 0 && bs->label == nullptr) { - error(token, "'continue' only allowed in loops"); + error(token, "'continue' only allowed in non-inline loops"); } break; case Token_fallthrough: diff --git a/src/check_type.cpp b/src/check_type.cpp index 010b31f03..089e66c4d 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -2434,6 +2434,13 @@ void set_procedure_abi_types(gbAllocator allocator, Type *type) { } break; } + + if (build_context.ODIN_OS == "linux" || + build_context.ODIN_OS == "darwin") { + if (is_type_pointer(new_type) & !is_type_pointer(e->type)) { + e->flags |= EntityFlag_ByVal; + } + } } } diff --git a/src/checker.cpp b/src/checker.cpp index 0494bde4b..c8b737df8 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -806,6 +806,7 @@ void init_checker_info(CheckerInfo *i) { map_init(&i->packages, a); array_init(&i->variable_init_order, a); array_init(&i->required_foreign_imports_through_force, a); + array_init(&i->required_global_variables, a); i->allow_identifier_uses = build_context.query_data_set_settings.kind == QueryDataSet_GoToDefinitions; if (i->allow_identifier_uses) { @@ -827,6 +828,7 @@ void destroy_checker_info(CheckerInfo *i) { array_free(&i->variable_init_order); array_free(&i->identifier_uses); array_free(&i->required_foreign_imports_through_force); + array_free(&i->required_global_variables); } @@ -1748,6 +1750,12 @@ void generate_minimum_dependency_set(Checker *c, Entity *start) { add_dependency_to_set(c, e); } + for_array(i, c->info.required_global_variables) { + Entity *e = c->info.required_global_variables[i]; + e->flags |= EntityFlag_Used; + add_dependency_to_set(c, e); + } + add_dependency_to_set(c, start); } @@ -2334,7 +2342,13 @@ DECL_ATTRIBUTE_PROC(var_decl_attribute) { return true; } - if (name == "export") { + if (name == "require") { + if (value != nullptr) { + error(elem, "'static' does not have any parameters"); + } + ac->require_declaration = true; + return true; + } else if (name == "export") { ExactValue ev = check_decl_attribute_value(c, value); if (ev.kind == ExactValue_Invalid) { ac->is_export = true; @@ -3297,11 +3311,11 @@ void check_add_import_decl(CheckerContext *ctx, Ast *decl) { } DECL_ATTRIBUTE_PROC(foreign_import_decl_attribute) { - if (name == "force") { + if (name == "force" || name == "require") { if (value != nullptr) { error(elem, "Expected no parameter for '%.*s'", LIT(name)); } - ac->force_foreign_import = true; + ac->require_declaration = true; return true; } return false; @@ -3354,7 +3368,7 @@ void check_add_foreign_import_decl(CheckerContext *ctx, Ast *decl) { AttributeContext ac = {}; check_decl_attributes(ctx, fl->attributes, foreign_import_decl_attribute, &ac); - if (ac.force_foreign_import) { + if (ac.require_declaration) { array_add(&ctx->info->required_foreign_imports_through_force, e); add_entity_use(ctx, nullptr, e); } diff --git a/src/checker.hpp b/src/checker.hpp index e1330478e..39ab94c70 100644 --- a/src/checker.hpp +++ b/src/checker.hpp @@ -98,7 +98,7 @@ struct AttributeContext { bool is_export; bool is_static; bool require_results; - bool force_foreign_import; + bool require_declaration; bool has_disabled_proc; bool disabled_proc; String link_name; @@ -260,6 +260,7 @@ struct CheckerInfo { PtrSet<isize> minimum_dependency_type_info_set; Array<Entity *> required_foreign_imports_through_force; + Array<Entity *> required_global_variables; bool allow_identifier_uses; diff --git a/src/entity.cpp b/src/entity.cpp index 49bce00df..dbe4f926c 100644 --- a/src/entity.cpp +++ b/src/entity.cpp @@ -45,14 +45,15 @@ enum EntityFlag { EntityFlag_TypeField = 1<<9, EntityFlag_Value = 1<<10, EntityFlag_Sret = 1<<11, - EntityFlag_BitFieldValue = 1<<12, - EntityFlag_PolyConst = 1<<13, - EntityFlag_NotExported = 1<<14, - EntityFlag_ConstInput = 1<<15, + EntityFlag_ByVal = 1<<12, + EntityFlag_BitFieldValue = 1<<13, + EntityFlag_PolyConst = 1<<14, + EntityFlag_NotExported = 1<<15, + EntityFlag_ConstInput = 1<<16, - EntityFlag_Static = 1<<16, + EntityFlag_Static = 1<<17, - EntityFlag_ImplicitReference = 1<<17, // NOTE(bill): equivalent to `const &` in C++ + EntityFlag_ImplicitReference = 1<<18, // NOTE(bill): equivalent to `const &` in C++ EntityFlag_SoaPtrField = 1<<19, // to allow s.x[0] where `s.x` is a pointer rather than a slice diff --git a/src/ir.cpp b/src/ir.cpp index 16999a209..ab6cbb151 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -10096,6 +10096,8 @@ void ir_build_stmt_internal(irProcedure *proc, Ast *node) { ir_emit_comment(proc, str_lit("InlineRangeStmt")); ir_open_scope(proc); // Open scope here + irBlock *done = ir_new_block(proc, node, "inline.for.done"); + Type *val0_type = nullptr; Type *val1_type = nullptr; if (rs->val0 != nullptr && !is_blank_ident(rs->val0)) { @@ -10114,8 +10116,6 @@ void ir_build_stmt_internal(irProcedure *proc, Ast *node) { irValue *val = nullptr; irValue *key = nullptr; - irBlock *loop = nullptr; - irBlock *done = nullptr; Ast *expr = unparen_expr(rs->expr); TypeAndValue tav = type_and_value_of_expr(expr); @@ -10141,8 +10141,12 @@ void ir_build_stmt_internal(irProcedure *proc, Ast *node) { compare_exact_values(Token_LtEq, val, end); val = exact_value_increment_one(val), index = exact_value_increment_one(index)) { + irBlock *body = ir_new_block(proc, node, "inline.for.body"); + ir_emit_jump(proc, body); + if (val0_type) ir_addr_store(proc, val0_addr, ir_value_constant(val0_type, val)); if (val1_type) ir_addr_store(proc, val1_addr, ir_value_constant(val1_type, index)); + ir_start_block(proc, body); ir_build_stmt(proc, rs->body); } @@ -10152,14 +10156,17 @@ void ir_build_stmt_internal(irProcedure *proc, Ast *node) { compare_exact_values(Token_Lt, val, end); val = exact_value_increment_one(val), index = exact_value_increment_one(index)) { + irBlock *body = ir_new_block(proc, node, "inline.for.body"); + ir_emit_jump(proc, body); + ir_start_block(proc, body); + if (val0_type) ir_addr_store(proc, val0_addr, ir_value_constant(val0_type, val)); if (val1_type) ir_addr_store(proc, val1_addr, ir_value_constant(val1_type, index)); + ir_build_stmt(proc, rs->body); } } - - } else if (tav.mode == Addressing_Type) { GB_ASSERT(is_type_enum(type_deref(tav.type))); Type *et = type_deref(tav.type); @@ -10171,6 +10178,10 @@ void ir_build_stmt_internal(irProcedure *proc, Ast *node) { if (val1_type) val1_addr = ir_build_addr(proc, rs->val1); for_array(i, bet->Enum.fields) { + irBlock *body = ir_new_block(proc, node, "inline.for.body"); + ir_emit_jump(proc, body); + ir_start_block(proc, body); + Entity *field = bet->Enum.fields[i]; GB_ASSERT(field->kind == Entity_Constant); if (val0_type) ir_addr_store(proc, val0_addr, ir_value_constant(val0_type, field->Constant.value)); @@ -10199,6 +10210,10 @@ void ir_build_stmt_internal(irProcedure *proc, Ast *node) { Rune codepoint = 0; isize offset = 0; do { + irBlock *body = ir_new_block(proc, node, "inline.for.body"); + ir_emit_jump(proc, body); + ir_start_block(proc, body); + isize width = gb_utf8_decode(str.text+offset, str.len-offset, &codepoint); if (val0_type) ir_addr_store(proc, val0_addr, ir_value_constant(val0_type, exact_value_i64(codepoint))); if (val1_type) ir_addr_store(proc, val1_addr, ir_value_constant(val1_type, exact_value_i64(offset))); @@ -10214,6 +10229,10 @@ void ir_build_stmt_internal(irProcedure *proc, Ast *node) { irValue *val_addr = ir_address_from_load_or_generate_local(proc, val); for (i64 i = 0; i < t->Array.count; i++) { + irBlock *body = ir_new_block(proc, node, "inline.for.body"); + ir_emit_jump(proc, body); + ir_start_block(proc, body); + if (val0_type) { // NOTE(bill): Due to weird legacy issues in LLVM, this needs to be an i32 irValue *elem = ir_emit_array_epi(proc, val_addr, cast(i32)i); @@ -10232,6 +10251,10 @@ void ir_build_stmt_internal(irProcedure *proc, Ast *node) { irValue *val_addr = ir_address_from_load_or_generate_local(proc, val); for (i64 i = 0; i < t->EnumeratedArray.count; i++) { + irBlock *body = ir_new_block(proc, node, "inline.for.body"); + ir_emit_jump(proc, body); + ir_start_block(proc, body); + if (val0_type) { // NOTE(bill): Due to weird legacy issues in LLVM, this needs to be an i32 irValue *elem = ir_emit_array_epi(proc, val_addr, cast(i32)i); @@ -10253,6 +10276,8 @@ void ir_build_stmt_internal(irProcedure *proc, Ast *node) { } } + ir_emit_jump(proc, done); + ir_start_block(proc, done); ir_close_scope(proc, irDeferExit_Default, nullptr); case_end; @@ -11815,6 +11840,8 @@ void ir_gen_tree(irGen *s) { if (!ir_min_dep_entity(m, e)) { continue; } + + DeclInfo *decl = decl_info_of_entity(e); if (decl == nullptr) { continue; diff --git a/src/ir_print.cpp b/src/ir_print.cpp index 4e5838785..32cc3809d 100644 --- a/src/ir_print.cpp +++ b/src/ir_print.cpp @@ -341,6 +341,10 @@ void ir_print_proc_type_without_pointer(irFileBuffer *f, irModule *m, Type *t) { // ir_fprintf(f, "* sret noalias "); // ir_write_string(f, str_lit("* noalias ")); ir_write_string(f, str_lit("*")); + if (build_context.ODIN_OS == "darwin" || + build_context.ODIN_OS == "linux") { + ir_fprintf(f, " byval"); + } if (param_count > 0 || t->Proc.calling_convention == ProcCC_Odin) { ir_write_string(f, str_lit(", ")); } @@ -363,6 +367,9 @@ void ir_print_proc_type_without_pointer(irFileBuffer *f, irModule *m, Type *t) { if (e->flags&EntityFlag_NoAlias) { ir_write_str_lit(f, " noalias"); } + if (e->flags&EntityFlag_ByVal) { + ir_write_str_lit(f, " byval"); + } ir_write_byte(f, ' '); param_index++; } @@ -2183,6 +2190,9 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) { if (e->flags&EntityFlag_NoAlias) { ir_write_str_lit(f, " noalias"); } + if (e->flags&EntityFlag_ByVal) { + ir_write_str_lit(f, " byval"); + } ir_write_byte(f, ' '); ir_print_value(f, m, arg, t); param_index++; @@ -2195,6 +2205,9 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) { if (e->flags&EntityFlag_ImplicitReference) { ir_write_str_lit(f, " nonnull dereferenceable"); } + if (e->flags&EntityFlag_ByVal) { + ir_write_str_lit(f, " byval"); + } ir_write_byte(f, ' '); irValue *arg = call->args[arg_index++]; ir_print_value(f, m, arg, t); @@ -2235,6 +2248,9 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) { if (e->flags&EntityFlag_NoAlias) { ir_write_str_lit(f, " noalias"); } + if (e->flags&EntityFlag_ByVal) { + ir_write_str_lit(f, " byval"); + } ir_write_byte(f, ' '); ir_print_value(f, m, arg, t); param_index++; @@ -2245,6 +2261,9 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) { if (e->flags&EntityFlag_NoAlias) { ir_write_str_lit(f, " noalias"); } + if (e->flags&EntityFlag_ByVal) { + ir_write_str_lit(f, " byval"); + } ir_write_byte(f, ' '); ir_print_value(f, m, arg, t); param_index++; @@ -2363,6 +2382,10 @@ void ir_print_proc(irFileBuffer *f, irModule *m, irProcedure *proc) { if (proc_type->return_by_pointer) { ir_print_type(f, m, reduce_tuple_to_single_type(proc_type->results)); ir_write_str_lit(f, "* sret noalias "); + if (build_context.ODIN_OS == "darwin" || + build_context.ODIN_OS == "linux") { + ir_fprintf(f, "byval "); + } ir_write_str_lit(f, "%agg.result"); param_index += 1; } @@ -2389,6 +2412,10 @@ void ir_print_proc(irFileBuffer *f, irModule *m, irProcedure *proc) { if (e->flags&EntityFlag_NoAlias) { ir_write_str_lit(f, " noalias"); } + if (e->flags&EntityFlag_ByVal) { + ir_write_str_lit(f, " byval"); + } + if (proc->body != nullptr) { ir_fprintf(f, " %%_.%td", parameter_index+j); @@ -2401,6 +2428,9 @@ void ir_print_proc(irFileBuffer *f, irModule *m, irProcedure *proc) { if (e->flags&EntityFlag_NoAlias) { ir_write_str_lit(f, " noalias"); } + if (e->flags&EntityFlag_ByVal) { + ir_write_str_lit(f, " byval"); + } if (proc->body != nullptr) { ir_fprintf(f, " %%_.%td", parameter_index); } |