From 55c9ae119382add2b840ae6526884bc9d99c9994 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 31 Jan 2016 01:51:33 -0700 Subject: [PATCH] codegen extern global variables correctly --- src/codegen.cpp | 38 +++++++++++++++++++++++--------------- src/parser.cpp | 27 +++++++++++++++++++++------ 2 files changed, 44 insertions(+), 21 deletions(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index f3c0b72c20..88bebc56a4 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -2533,26 +2533,34 @@ static void do_code_gen(CodeGen *g) { continue; } - // TODO if the global is exported, set external linkage - LLVMValueRef init_val; - assert(var->decl_node); assert(var->decl_node->type == NodeTypeVariableDeclaration); - AstNode *expr_node = var->decl_node->data.variable_declaration.expr; - if (expr_node) { - Expr *expr = get_resolved_expr(expr_node); - ConstExprValue *const_val = &expr->const_val; - assert(const_val->ok); - TypeTableEntry *type_entry = expr->type_entry; - init_val = gen_const_val(g, type_entry, const_val); + + LLVMValueRef global_value; + if (var->decl_node->data.variable_declaration.is_extern) { + global_value = LLVMAddGlobal(g->module, var->type->type_ref, buf_ptr(&var->name)); + + LLVMSetLinkage(global_value, LLVMExternalLinkage); } else { - init_val = LLVMConstNull(var->type->type_ref); + AstNode *expr_node = var->decl_node->data.variable_declaration.expr; + LLVMValueRef init_val; + if (expr_node) { + Expr *expr = get_resolved_expr(expr_node); + ConstExprValue *const_val = &expr->const_val; + assert(const_val->ok); + TypeTableEntry *type_entry = expr->type_entry; + init_val = gen_const_val(g, type_entry, const_val); + } else { + init_val = LLVMConstNull(var->type->type_ref); + } + + global_value = LLVMAddGlobal(g->module, LLVMTypeOf(init_val), buf_ptr(&var->name)); + LLVMSetInitializer(global_value, init_val); + LLVMSetLinkage(global_value, LLVMInternalLinkage); + LLVMSetUnnamedAddr(global_value, true); } - LLVMValueRef global_value = LLVMAddGlobal(g->module, LLVMTypeOf(init_val), buf_ptr(&var->name)); - LLVMSetInitializer(global_value, init_val); + LLVMSetGlobalConstant(global_value, var->is_const); - LLVMSetUnnamedAddr(global_value, true); - LLVMSetLinkage(global_value, LLVMInternalLinkage); var->value_ref = global_value; } diff --git a/src/parser.cpp b/src/parser.cpp index 67d2c21312..f81206357f 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -2256,7 +2256,7 @@ static AstNode *ast_parse_fn_def(ParseContext *pc, int *token_index, bool mandat } /* -ExternDecl : "extern" FnProto ";" +ExternDecl = "extern" (FnProto | VariableDeclaration) ";" */ static AstNode *ast_parse_extern_decl(ParseContext *pc, int *token_index, bool mandatory, ZigList *directives, VisibMod visib_mod) @@ -2271,13 +2271,28 @@ static AstNode *ast_parse_extern_decl(ParseContext *pc, int *token_index, bool m } *token_index += 1; - AstNode *node = ast_parse_fn_proto(pc, token_index, true, directives, visib_mod); + AstNode *fn_proto_node = ast_parse_fn_proto(pc, token_index, false, directives, visib_mod); + if (fn_proto_node) { + ast_eat_token(pc, token_index, TokenIdSemicolon); - ast_eat_token(pc, token_index, TokenIdSemicolon); + fn_proto_node->data.fn_proto.is_extern = true; - node->data.fn_proto.is_extern = true; - normalize_parent_ptrs(node); - return node; + normalize_parent_ptrs(fn_proto_node); + return fn_proto_node; + } + + AstNode *var_decl_node = ast_parse_variable_declaration_expr(pc, token_index, false, directives, visib_mod); + if (var_decl_node) { + ast_eat_token(pc, token_index, TokenIdSemicolon); + + var_decl_node->data.variable_declaration.is_extern = true; + + normalize_parent_ptrs(var_decl_node); + return var_decl_node; + } + + Token *token = &pc->tokens->at(*token_index); + ast_invalid_token_error(pc, token); } /*