Commit 4dc2b82506
Changed files (4)
src/analyze.cpp
@@ -1027,8 +1027,8 @@ static TypeTableEntry *analyze_bin_op_expr(CodeGen *g, ImportTableEntry *import,
{
AstNode *op1 = node->data.bin_op_expr.op1;
AstNode *op2 = node->data.bin_op_expr.op2;
- TypeTableEntry *lhs_type = analyze_expression(g, import, context, nullptr, op1);
- TypeTableEntry *rhs_type = analyze_expression(g, import, context, nullptr, op2);
+ TypeTableEntry *lhs_type = analyze_expression(g, import, context, expected_type, op1);
+ TypeTableEntry *rhs_type = analyze_expression(g, import, context, expected_type, op2);
TypeTableEntry *return_type = nullptr;
@@ -1191,21 +1191,25 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
case NodeTypeReturnExpr:
{
- TypeTableEntry *expected_return_type = get_return_type(context);
- TypeTableEntry *actual_return_type;
- if (node->data.return_expr.expr) {
- actual_return_type = analyze_expression(g, import, context, expected_return_type, node->data.return_expr.expr);
- } else {
- actual_return_type = g->builtin_types.entry_void;
- }
+ if (context->fn_entry) {
+ TypeTableEntry *expected_return_type = get_return_type(context);
+ TypeTableEntry *actual_return_type;
+ if (node->data.return_expr.expr) {
+ actual_return_type = analyze_expression(g, import, context, expected_return_type, node->data.return_expr.expr);
+ } else {
+ actual_return_type = g->builtin_types.entry_void;
+ }
- if (actual_return_type->id == TypeTableEntryIdUnreachable) {
- // "return exit(0)" should just be "exit(0)".
- add_node_error(g, node, buf_sprintf("returning is unreachable"));
- actual_return_type = g->builtin_types.entry_invalid;
- }
+ if (actual_return_type->id == TypeTableEntryIdUnreachable) {
+ // "return exit(0)" should just be "exit(0)".
+ add_node_error(g, node, buf_sprintf("returning is unreachable"));
+ actual_return_type = g->builtin_types.entry_invalid;
+ }
- check_type_compatibility(g, node, expected_return_type, actual_return_type);
+ check_type_compatibility(g, node, expected_return_type, actual_return_type);
+ } else {
+ add_node_error(g, node, buf_sprintf("return expression outside function definition"));
+ }
return_type = g->builtin_types.entry_unreachable;
break;
}
src/analyze.hpp
@@ -270,6 +270,10 @@ struct NumberLiteralNode {
TypeTableEntry *resolved_type;
};
+struct VarDeclNode {
+ TypeTableEntry *type;
+};
+
struct CodeGenNode {
union {
TypeNode type_node; // for NodeTypeType
@@ -282,6 +286,7 @@ struct CodeGenNode {
FieldAccessNode field_access_node; // for NodeTypeFieldAccessExpr
CastNode cast_node; // for NodeTypeCastExpr
NumberLiteralNode num_lit_node; // for NodeTypeNumberLiteral
+ VarDeclNode var_decl_node; // for NodeTypeVariableDeclaration
} data;
ExprNode expr_node; // for all the expression nodes
};
src/codegen.cpp
@@ -103,6 +103,8 @@ static int count_non_void_params(CodeGen *g, ZigList<AstNode *> *params) {
}
static void add_debug_source_node(CodeGen *g, AstNode *node) {
+ if (!g->cur_block_context)
+ return;
LLVMZigSetCurrentDebugLocation(g->builder, node->line + 1, node->column + 1,
g->cur_block_context->di_scope);
}
@@ -1040,12 +1042,16 @@ static void do_code_gen(CodeGen *g) {
for (int i = 0; i < g->global_vars.length; i += 1) {
VariableTableEntry *var = g->global_vars.at(i);
- LLVMValueRef init_val = gen_expr(g, var->decl_node->data.variable_declaration.expr);
-
// TODO if the global is exported, set external linkage
- LLVMValueRef global_value = LLVMAddGlobal(g->module, LLVMTypeOf(init_val), "");
+ LLVMValueRef global_value = LLVMAddGlobal(g->module, var->type->type_ref, "");
LLVMSetLinkage(global_value, LLVMPrivateLinkage);
- LLVMSetInitializer(global_value, init_val);
+
+ if (var->is_const) {
+ LLVMValueRef init_val = gen_expr(g, var->decl_node->data.variable_declaration.expr);
+ LLVMSetInitializer(global_value, init_val);
+ } else {
+ LLVMSetInitializer(global_value, LLVMConstNull(var->type->type_ref));
+ }
LLVMSetGlobalConstant(global_value, var->is_const);
LLVMSetUnnamedAddr(global_value, true);
test/run_tests.cpp
@@ -496,6 +496,21 @@ fn test_foo(foo : Foo) {
if foo.b {
print_str("OK\n" as string);
}
+}
+ )SOURCE", "OK\n");
+
+ add_simple_case("global variables", R"SOURCE(
+use "std.zig";
+
+const g1 : i32 = 1233 + 1;
+var g2 : i32;
+
+export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
+ if g2 != 0 { print_str("BAD\n" as string); }
+ g2 = g1;
+ if g2 != 1234 { print_str("BAD\n" as string); }
+ print_str("OK\n" as string);
+ return 0;
}
)SOURCE", "OK\n");
}
@@ -682,6 +697,13 @@ fn f() {
add_compile_fail_case("variadic functions only allowed in extern", R"SOURCE(
fn f(...) {}
)SOURCE", 1, ".tmp_source.zig:2:1: error: variadic arguments only allowed in extern functions");
+
+ add_compile_fail_case("write to const global variable", R"SOURCE(
+const x : i32 = 99;
+fn f() {
+ x = 1;
+}
+ )SOURCE", 1, ".tmp_source.zig:4:5: error: cannot assign to constant variable");
}
static void print_compiler_invocation(TestCase *test_case) {