authorgravatar for andrea@orru.ioAndrea Orru <andrea@orru.io> 2018-01-07 04:43:15-05:00
committergravatar for andrea@orru.ioAndrea Orru <andrea@orru.io> 2018-01-07 04:43:15-05:00
logde1f57926f212f18a98884fa8b1d0df7f7bc7f03
tree779595179f9a556e04d8a159ae15f6e8b669d13d
parent31828572249883f99fad307dc6b27df9d1678a8d
parent32ba0dcea953a044b509081b583b3eed3b27b577

Merge branch 'master' of github.com:zig-lang/zig


5 files changed, 97 insertions(+), 48 deletions(-)

doc/langref.html.in+3-4
......@@ -264,15 +264,14 @@
264264 please <a href="https://github.com/zig-lang/www.ziglang.org/issues/new?title=I%20searched%20for%20___%20in%20the%20docs%20and%20didn%27t%20find%20it">file an issue</a> or <a href="https://webchat.freenode.net/?channels=%23zig">say something on IRC</a>.
265265 </p>
266266 <h2 id="hello-world">Hello World</h2>
267 <pre><code class="zig">const io = @import("std").io;
267 <pre><code class="zig">const std = @import("std");
268268
269269pub fn main() -&gt; %void {
270270 // If this program is run without stdout attached, exit with an error.
271 var stdout_file = %return io.getStdOut();
272 const stdout = &amp;stdout_file.out_stream;
271 var stdout_file = %return std.io.getStdOut();
273272 // If this program encounters pipe failure when printing to stdout, exit
274273 // with an error.
275 %return stdout.print("Hello, world!\n");
274 %return stdout_file.write("Hello, world!\n");
276275}</code></pre>
277276 <pre><code class="sh">$ zig build-exe hello.zig
278277$ ./hello
src/all_types.hpp+3-8
......@@ -37,13 +37,7 @@ struct ScopeDecls;
3737struct ZigWindowsSDK;
3838struct Tld;
3939struct TldExport;
40
41struct IrGotoItem {
42 AstNode *source_node;
43 IrBasicBlock *bb;
44 size_t instruction_index;
45 Scope *scope;
46};
40struct IrAnalyze;
4741
4842struct IrExecutable {
4943 ZigList<IrBasicBlock *> basic_block_list;
......@@ -53,13 +47,13 @@ struct IrExecutable {
5347 size_t *backward_branch_count;
5448 size_t backward_branch_quota;
5549 bool invalid;
56 ZigList<IrGotoItem> goto_list;
5750 bool is_inline;
5851 FnTableEntry *fn_entry;
5952 Buf *c_import_buf;
6053 AstNode *source_node;
6154 IrExecutable *parent_exec;
6255 IrExecutable *source_exec;
56 IrAnalyze *analysis;
6357 Scope *begin_scope;
6458 ZigList<Tld *> tld_list;
6559};
......@@ -1626,6 +1620,7 @@ struct VariableTableEntry {
16261620 LLVMValueRef param_value_ref;
16271621 bool shadowable;
16281622 size_t mem_slot_index;
1623 IrExecutable *owner_exec;
16291624 size_t ref_count;
16301625 VarLinkage linkage;
16311626 IrInstruction *decl_instruction;
src/ir.cpp+48-36
......@@ -2530,8 +2530,10 @@ static VariableTableEntry *ir_create_var(IrBuilder *irb, AstNode *node, Scope *s
25302530 bool src_is_const, bool gen_is_const, bool is_shadowable, IrInstruction *is_comptime)
25312531{
25322532 VariableTableEntry *var = create_local_var(irb->codegen, node, scope, name, src_is_const, gen_is_const, is_shadowable, is_comptime);
2533 if (is_comptime != nullptr || gen_is_const)
2533 if (is_comptime != nullptr || gen_is_const) {
25342534 var->mem_slot_index = exec_next_mem_slot(irb->exec);
2535 var->owner_exec = irb->exec;
2536 }
25352537 assert(var->child_scope);
25362538 return var;
25372539}
......@@ -7037,48 +7039,48 @@ IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node
70377039 if (expected_type != nullptr && type_is_invalid(expected_type))
70387040 return codegen->invalid_instruction;
70397041
7040 IrExecutable ir_executable = {0};
7041 ir_executable.source_node = source_node;
7042 ir_executable.parent_exec = parent_exec;
7043 ir_executable.name = exec_name;
7044 ir_executable.is_inline = true;
7045 ir_executable.fn_entry = fn_entry;
7046 ir_executable.c_import_buf = c_import_buf;
7047 ir_executable.begin_scope = scope;
7048 ir_gen(codegen, node, scope, &ir_executable);
7049
7050 if (ir_executable.invalid)
7042 IrExecutable *ir_executable = allocate<IrExecutable>(1);
7043 ir_executable->source_node = source_node;
7044 ir_executable->parent_exec = parent_exec;
7045 ir_executable->name = exec_name;
7046 ir_executable->is_inline = true;
7047 ir_executable->fn_entry = fn_entry;
7048 ir_executable->c_import_buf = c_import_buf;
7049 ir_executable->begin_scope = scope;
7050 ir_gen(codegen, node, scope, ir_executable);
7051
7052 if (ir_executable->invalid)
70517053 return codegen->invalid_instruction;
70527054
70537055 if (codegen->verbose_ir) {
70547056 fprintf(stderr, "\nSource: ");
70557057 ast_render(codegen, stderr, node, 4);
70567058 fprintf(stderr, "\n{ // (IR)\n");
7057 ir_print(codegen, stderr, &ir_executable, 4);
7059 ir_print(codegen, stderr, ir_executable, 4);
70587060 fprintf(stderr, "}\n");
70597061 }
7060 IrExecutable analyzed_executable = {0};
7061 analyzed_executable.source_node = source_node;
7062 analyzed_executable.parent_exec = parent_exec;
7063 analyzed_executable.source_exec = &ir_executable;
7064 analyzed_executable.name = exec_name;
7065 analyzed_executable.is_inline = true;
7066 analyzed_executable.fn_entry = fn_entry;
7067 analyzed_executable.c_import_buf = c_import_buf;
7068 analyzed_executable.backward_branch_count = backward_branch_count;
7069 analyzed_executable.backward_branch_quota = backward_branch_quota;
7070 analyzed_executable.begin_scope = scope;
7071 TypeTableEntry *result_type = ir_analyze(codegen, &ir_executable, &analyzed_executable, expected_type, node);
7062 IrExecutable *analyzed_executable = allocate<IrExecutable>(1);
7063 analyzed_executable->source_node = source_node;
7064 analyzed_executable->parent_exec = parent_exec;
7065 analyzed_executable->source_exec = ir_executable;
7066 analyzed_executable->name = exec_name;
7067 analyzed_executable->is_inline = true;
7068 analyzed_executable->fn_entry = fn_entry;
7069 analyzed_executable->c_import_buf = c_import_buf;
7070 analyzed_executable->backward_branch_count = backward_branch_count;
7071 analyzed_executable->backward_branch_quota = backward_branch_quota;
7072 analyzed_executable->begin_scope = scope;
7073 TypeTableEntry *result_type = ir_analyze(codegen, ir_executable, analyzed_executable, expected_type, node);
70727074 if (type_is_invalid(result_type))
70737075 return codegen->invalid_instruction;
70747076
70757077 if (codegen->verbose_ir) {
70767078 fprintf(stderr, "{ // (analyzed)\n");
7077 ir_print(codegen, stderr, &analyzed_executable, 4);
7079 ir_print(codegen, stderr, analyzed_executable, 4);
70787080 fprintf(stderr, "}\n");
70797081 }
70807082
7081 return ir_exec_const_result(codegen, &analyzed_executable);
7083 return ir_exec_const_result(codegen, analyzed_executable);
70827084}
70837085
70847086static TypeTableEntry *ir_resolve_type(IrAnalyze *ira, IrInstruction *type_value) {
......@@ -9334,6 +9336,8 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc
93349336 IrInstruction *casted_init_value = ir_implicit_cast(ira, init_value, explicit_type);
93359337 bool is_comptime_var = ir_get_var_is_comptime(var);
93369338
9339 bool var_class_requires_const = false;
9340
93379341 TypeTableEntry *result_type = casted_init_value->value.type;
93389342 if (type_is_invalid(result_type)) {
93399343 result_type = ira->codegen->builtin_types.entry_invalid;
......@@ -9345,6 +9349,7 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc
93459349 result_type = ira->codegen->builtin_types.entry_invalid;
93469350 break;
93479351 case VarClassRequiredConst:
9352 var_class_requires_const = true;
93489353 if (!var->src_is_const && !is_comptime_var) {
93499354 ir_add_error_node(ira, source_node,
93509355 buf_sprintf("variable of type '%s' must be const or comptime",
......@@ -9366,8 +9371,6 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc
93669371 return ira->codegen->builtin_types.entry_void;
93679372 }
93689373
9369 bool is_comptime = ir_get_var_is_comptime(var);
9370
93719374 if (decl_var_instruction->align_value == nullptr) {
93729375 var->align_bytes = get_abi_alignment(ira->codegen, result_type);
93739376 } else {
......@@ -9382,12 +9385,12 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc
93829385 ConstExprValue *mem_slot = &ira->exec_context.mem_slot_list[var->mem_slot_index];
93839386 *mem_slot = casted_init_value->value;
93849387
9385 if (is_comptime) {
9388 if (is_comptime_var || (var_class_requires_const && var->gen_is_const)) {
93869389 ir_build_const_from(ira, &decl_var_instruction->base);
93879390 return ira->codegen->builtin_types.entry_void;
93889391 }
93899392 }
9390 } else if (is_comptime) {
9393 } else if (is_comptime_var) {
93919394 ir_add_error(ira, &decl_var_instruction->base,
93929395 buf_sprintf("cannot store runtime value in compile time variable"));
93939396 var->value->type = ira->codegen->builtin_types.entry_invalid;
......@@ -9690,6 +9693,10 @@ static VariableTableEntry *get_fn_var_by_index(FnTableEntry *fn_entry, size_t in
96909693static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction,
96919694 VariableTableEntry *var, bool is_const_ptr, bool is_volatile_ptr)
96929695{
9696 if (var->mem_slot_index != SIZE_MAX && var->owner_exec->analysis == nullptr) {
9697 assert(ira->codegen->errors.length != 0);
9698 return ira->codegen->invalid_instruction;
9699 }
96939700 assert(var->value->type);
96949701 if (type_is_invalid(var->value->type))
96959702 return ira->codegen->invalid_instruction;
......@@ -9700,9 +9707,14 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction,
97009707 if (var->value->special == ConstValSpecialStatic) {
97019708 mem_slot = var->value;
97029709 } else {
9703 // TODO once the analyze code is fully ported over to IR we won't need this SIZE_MAX thing.
9704 if (var->mem_slot_index != SIZE_MAX && (comptime_var_mem || var->gen_is_const))
9705 mem_slot = &ira->exec_context.mem_slot_list[var->mem_slot_index];
9710 if (var->mem_slot_index != SIZE_MAX && (comptime_var_mem || var->gen_is_const)) {
9711 // find the relevant exec_context
9712 assert(var->owner_exec != nullptr);
9713 assert(var->owner_exec->analysis != nullptr);
9714 IrExecContext *exec_context = &var->owner_exec->analysis->exec_context;
9715 assert(var->mem_slot_index < exec_context->mem_slot_count);
9716 mem_slot = &exec_context->mem_slot_list[var->mem_slot_index];
9717 }
97069718 }
97079719
97089720 bool is_const = (var->value->type->id == TypeTableEntryIdMetaType) ? is_const_ptr : var->src_is_const;
......@@ -15328,8 +15340,8 @@ TypeTableEntry *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutabl
1532815340 assert(!old_exec->invalid);
1532915341 assert(expected_type == nullptr || !type_is_invalid(expected_type));
1533015342
15331 IrAnalyze ir_analyze_data = {};
15332 IrAnalyze *ira = &ir_analyze_data;
15343 IrAnalyze *ira = allocate<IrAnalyze>(1);
15344 old_exec->analysis = ira;
1533315345 ira->codegen = codegen;
1533415346 ira->explicit_return_type = expected_type;
1533515347
test/cases/misc.zig+31
......@@ -577,3 +577,34 @@ test "implicit comptime while" {
577577 @compileError("bad");
578578 }
579579}
580
581test "struct inside function" {
582 testStructInFn();
583 comptime testStructInFn();
584}
585
586fn testStructInFn() {
587 const BlockKind = u32;
588
589 const Block = struct {
590 kind: BlockKind,
591 };
592
593 var block = Block { .kind = 1234 };
594
595 block.kind += 1;
596
597 assert(block.kind == 1235);
598}
599
600fn fnThatClosesOverLocalConst() -> type {
601 const c = 1;
602 return struct {
603 fn g() -> i32 { return c; }
604 };
605}
606
607test "function closes over local const" {
608 const x = fnThatClosesOverLocalConst().g();
609 assert(x == 1);
610}
test/compile_errors.zig+12
......@@ -1,6 +1,18 @@
11const tests = @import("tests.zig");
22
33pub fn addCases(cases: &tests.CompileErrorContext) {
4 cases.add("bad identifier in function with struct defined inside function which references local const",
5 \\export fn entry() {
6 \\ const BlockKind = u32;
7 \\
8 \\ const Block = struct {
9 \\ kind: BlockKind,
10 \\ };
11 \\
12 \\ bogus;
13 \\}
14 , ".tmp_source.zig:8:5: error: use of undeclared identifier 'bogus'");
15
416 cases.add("labeled break not found",
517 \\export fn entry() {
618 \\ blah: while (true) {