| author | |
| committer | |
| log | 4dc2b8250638efda3a9990182f46ad57c403b28b |
| tree | 25ced26eb3a257753ac0b877326eea82697960d1 |
| parent | 83b68c9f13c90dfbbd2735cde4ef570ac50476c0 |
4 files changed, 56 insertions(+), 19 deletions(-)
src/analyze.cpp+19-15| ... | @@ -1027,8 +1027,8 @@ static TypeTableEntry *analyze_bin_op_expr(CodeGen *g, ImportTableEntry *import, | ... | @@ -1027,8 +1027,8 @@ static TypeTableEntry *analyze_bin_op_expr(CodeGen *g, ImportTableEntry *import, |
| 1027 | { | 1027 | { |
| 1028 | AstNode *op1 = node->data.bin_op_expr.op1; | 1028 | AstNode *op1 = node->data.bin_op_expr.op1; |
| 1029 | AstNode *op2 = node->data.bin_op_expr.op2; | 1029 | AstNode *op2 = node->data.bin_op_expr.op2; |
| 1030 | TypeTableEntry *lhs_type = analyze_expression(g, import, context, nullptr, op1); | 1030 | TypeTableEntry *lhs_type = analyze_expression(g, import, context, expected_type, op1); |
| 1031 | TypeTableEntry *rhs_type = analyze_expression(g, import, context, nullptr, op2); | 1031 | TypeTableEntry *rhs_type = analyze_expression(g, import, context, expected_type, op2); |
| 1032 | 1032 | ||
| 1033 | TypeTableEntry *return_type = nullptr; | 1033 | TypeTableEntry *return_type = nullptr; |
| 1034 | 1034 | ||
| ... | @@ -1191,21 +1191,25 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, | ... | @@ -1191,21 +1191,25 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, |
| 1191 | 1191 | ||
| 1192 | case NodeTypeReturnExpr: | 1192 | case NodeTypeReturnExpr: |
| 1193 | { | 1193 | { |
| 1194 | TypeTableEntry *expected_return_type = get_return_type(context); | 1194 | if (context->fn_entry) { |
| 1195 | TypeTableEntry *actual_return_type; | 1195 | TypeTableEntry *expected_return_type = get_return_type(context); |
| 1196 | if (node->data.return_expr.expr) { | 1196 | TypeTableEntry *actual_return_type; |
| 1197 | actual_return_type = analyze_expression(g, import, context, expected_return_type, node->data.return_expr.expr); | 1197 | if (node->data.return_expr.expr) { |
| 1198 | } else { | 1198 | actual_return_type = analyze_expression(g, import, context, expected_return_type, node->data.return_expr.expr); |
| 1199 | actual_return_type = g->builtin_types.entry_void; | 1199 | } else { |
| 1200 | } | 1200 | actual_return_type = g->builtin_types.entry_void; |
| 1201 | } | ||
| 1201 | 1202 | ||
| 1202 | if (actual_return_type->id == TypeTableEntryIdUnreachable) { | 1203 | if (actual_return_type->id == TypeTableEntryIdUnreachable) { |
| 1203 | // "return exit(0)" should just be "exit(0)". | 1204 | // "return exit(0)" should just be "exit(0)". |
| 1204 | add_node_error(g, node, buf_sprintf("returning is unreachable")); | 1205 | add_node_error(g, node, buf_sprintf("returning is unreachable")); |
| 1205 | actual_return_type = g->builtin_types.entry_invalid; | 1206 | actual_return_type = g->builtin_types.entry_invalid; |
| 1206 | } | 1207 | } |
| 1207 | 1208 | ||
| 1208 | check_type_compatibility(g, node, expected_return_type, actual_return_type); | 1209 | check_type_compatibility(g, node, expected_return_type, actual_return_type); |
| 1210 | } else { | ||
| 1211 | add_node_error(g, node, buf_sprintf("return expression outside function definition")); | ||
| 1212 | } | ||
| 1209 | return_type = g->builtin_types.entry_unreachable; | 1213 | return_type = g->builtin_types.entry_unreachable; |
| 1210 | break; | 1214 | break; |
| 1211 | } | 1215 | } |
src/analyze.hpp+5| ... | @@ -270,6 +270,10 @@ struct NumberLiteralNode { | ... | @@ -270,6 +270,10 @@ struct NumberLiteralNode { |
| 270 | TypeTableEntry *resolved_type; | 270 | TypeTableEntry *resolved_type; |
| 271 | }; | 271 | }; |
| 272 | 272 | ||
| 273 | struct VarDeclNode { | ||
| 274 | TypeTableEntry *type; | ||
| 275 | }; | ||
| 276 | |||
| 273 | struct CodeGenNode { | 277 | struct CodeGenNode { |
| 274 | union { | 278 | union { |
| 275 | TypeNode type_node; // for NodeTypeType | 279 | TypeNode type_node; // for NodeTypeType |
| ... | @@ -282,6 +286,7 @@ struct CodeGenNode { | ... | @@ -282,6 +286,7 @@ struct CodeGenNode { |
| 282 | FieldAccessNode field_access_node; // for NodeTypeFieldAccessExpr | 286 | FieldAccessNode field_access_node; // for NodeTypeFieldAccessExpr |
| 283 | CastNode cast_node; // for NodeTypeCastExpr | 287 | CastNode cast_node; // for NodeTypeCastExpr |
| 284 | NumberLiteralNode num_lit_node; // for NodeTypeNumberLiteral | 288 | NumberLiteralNode num_lit_node; // for NodeTypeNumberLiteral |
| 289 | VarDeclNode var_decl_node; // for NodeTypeVariableDeclaration | ||
| 285 | } data; | 290 | } data; |
| 286 | ExprNode expr_node; // for all the expression nodes | 291 | ExprNode expr_node; // for all the expression nodes |
| 287 | }; | 292 | }; |
src/codegen.cpp+10-4| ... | @@ -103,6 +103,8 @@ static int count_non_void_params(CodeGen *g, ZigList<AstNode *> *params) { | ... | @@ -103,6 +103,8 @@ static int count_non_void_params(CodeGen *g, ZigList<AstNode *> *params) { |
| 103 | } | 103 | } |
| 104 | 104 | ||
| 105 | static void add_debug_source_node(CodeGen *g, AstNode *node) { | 105 | static void add_debug_source_node(CodeGen *g, AstNode *node) { |
| 106 | if (!g->cur_block_context) | ||
| 107 | return; | ||
| 106 | LLVMZigSetCurrentDebugLocation(g->builder, node->line + 1, node->column + 1, | 108 | LLVMZigSetCurrentDebugLocation(g->builder, node->line + 1, node->column + 1, |
| 107 | g->cur_block_context->di_scope); | 109 | g->cur_block_context->di_scope); |
| 108 | } | 110 | } |
| ... | @@ -1040,12 +1042,16 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -1040,12 +1042,16 @@ static void do_code_gen(CodeGen *g) { |
| 1040 | for (int i = 0; i < g->global_vars.length; i += 1) { | 1042 | for (int i = 0; i < g->global_vars.length; i += 1) { |
| 1041 | VariableTableEntry *var = g->global_vars.at(i); | 1043 | VariableTableEntry *var = g->global_vars.at(i); |
| 1042 | 1044 | ||
| 1043 | LLVMValueRef init_val = gen_expr(g, var->decl_node->data.variable_declaration.expr); | ||
| 1044 | |||
| 1045 | // TODO if the global is exported, set external linkage | 1045 | // TODO if the global is exported, set external linkage |
| 1046 | LLVMValueRef global_value = LLVMAddGlobal(g->module, LLVMTypeOf(init_val), ""); | 1046 | LLVMValueRef global_value = LLVMAddGlobal(g->module, var->type->type_ref, ""); |
| 1047 | LLVMSetLinkage(global_value, LLVMPrivateLinkage); | 1047 | LLVMSetLinkage(global_value, LLVMPrivateLinkage); |
| 1048 | LLVMSetInitializer(global_value, init_val); | 1048 | |
| 1049 | if (var->is_const) { | ||
| 1050 | LLVMValueRef init_val = gen_expr(g, var->decl_node->data.variable_declaration.expr); | ||
| 1051 | LLVMSetInitializer(global_value, init_val); | ||
| 1052 | } else { | ||
| 1053 | LLVMSetInitializer(global_value, LLVMConstNull(var->type->type_ref)); | ||
| 1054 | } | ||
| 1049 | LLVMSetGlobalConstant(global_value, var->is_const); | 1055 | LLVMSetGlobalConstant(global_value, var->is_const); |
| 1050 | LLVMSetUnnamedAddr(global_value, true); | 1056 | LLVMSetUnnamedAddr(global_value, true); |
| 1051 | 1057 |
test/run_tests.cpp+22| ... | @@ -496,6 +496,21 @@ fn test_foo(foo : Foo) { | ... | @@ -496,6 +496,21 @@ fn test_foo(foo : Foo) { |
| 496 | if foo.b { | 496 | if foo.b { |
| 497 | print_str("OK\n" as string); | 497 | print_str("OK\n" as string); |
| 498 | } | 498 | } |
| 499 | } | ||
| 500 | )SOURCE", "OK\n"); | ||
| 501 | |||
| 502 | add_simple_case("global variables", R"SOURCE( | ||
| 503 | use "std.zig"; | ||
| 504 | |||
| 505 | const g1 : i32 = 1233 + 1; | ||
| 506 | var g2 : i32; | ||
| 507 | |||
| 508 | export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 { | ||
| 509 | if g2 != 0 { print_str("BAD\n" as string); } | ||
| 510 | g2 = g1; | ||
| 511 | if g2 != 1234 { print_str("BAD\n" as string); } | ||
| 512 | print_str("OK\n" as string); | ||
| 513 | return 0; | ||
| 499 | } | 514 | } |
| 500 | )SOURCE", "OK\n"); | 515 | )SOURCE", "OK\n"); |
| 501 | } | 516 | } |
| ... | @@ -682,6 +697,13 @@ fn f() { | ... | @@ -682,6 +697,13 @@ fn f() { |
| 682 | add_compile_fail_case("variadic functions only allowed in extern", R"SOURCE( | 697 | add_compile_fail_case("variadic functions only allowed in extern", R"SOURCE( |
| 683 | fn f(...) {} | 698 | fn f(...) {} |
| 684 | )SOURCE", 1, ".tmp_source.zig:2:1: error: variadic arguments only allowed in extern functions"); | 699 | )SOURCE", 1, ".tmp_source.zig:2:1: error: variadic arguments only allowed in extern functions"); |
| 700 | |||
| 701 | add_compile_fail_case("write to const global variable", R"SOURCE( | ||
| 702 | const x : i32 = 99; | ||
| 703 | fn f() { | ||
| 704 | x = 1; | ||
| 705 | } | ||
| 706 | )SOURCE", 1, ".tmp_source.zig:4:5: error: cannot assign to constant variable"); | ||
| 685 | } | 707 | } |
| 686 | 708 | ||
| 687 | static void print_compiler_invocation(TestCase *test_case) { | 709 | static void print_compiler_invocation(TestCase *test_case) { |