diff options
| author | Andrew Kelley <superjoe30@gmail.com> | 2017-02-03 11:59:56 -0500 |
|---|---|---|
| committer | Andrew Kelley <superjoe30@gmail.com> | 2017-02-03 11:59:56 -0500 |
| commit | aae168550fa3d8b21478deb7198513dad8cc0b37 (patch) | |
| tree | 8e5f735f62abae03ef28d023d9c231b6541d706e | |
| parent | 71d335e5ccc5c7c37ac40debf78ad3aa096b22d3 (diff) | |
| download | zig-aae168550fa3d8b21478deb7198513dad8cc0b37.tar.gz zig-aae168550fa3d8b21478deb7198513dad8cc0b37.zip | |
exported global variables get emitted as external in LLVM
| -rw-r--r-- | src/all_types.hpp | 9 | ||||
| -rw-r--r-- | src/analyze.cpp | 20 | ||||
| -rw-r--r-- | src/ast_render.cpp | 2 | ||||
| -rw-r--r-- | src/codegen.cpp | 27 | ||||
| -rw-r--r-- | src/parseh.cpp | 2 |
5 files changed, 40 insertions, 20 deletions
diff --git a/src/all_types.hpp b/src/all_types.hpp index 4b971ea552..78888ce8ce 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -1278,7 +1278,12 @@ struct CodeGen { ConstExprValue const_void_val; }; -// TODO after merging IR branch, we can probably delete some of these fields +enum VarLinkage { + VarLinkageInternal, + VarLinkageExport, + VarLinkageExternal, +}; + struct VariableTableEntry { Buf name; ConstExprValue value; @@ -1297,7 +1302,7 @@ struct VariableTableEntry { bool shadowable; size_t mem_slot_index; size_t ref_count; - bool is_extern; + VarLinkage linkage; }; struct ErrorTableEntry { diff --git a/src/analyze.cpp b/src/analyze.cpp index 280fc94214..507101db44 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -1913,6 +1913,20 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) { AstNode *source_node = tld_var->base.source_node; + if (is_export && is_extern) { + add_node_error(g, source_node, buf_sprintf("variable is both export and extern")); + } + + VarLinkage linkage; + if (is_export) { + linkage = VarLinkageExport; + } else if (is_extern) { + linkage = VarLinkageExternal; + } else { + linkage = VarLinkageInternal; + } + + IrInstruction *init_value = nullptr; TypeTableEntry *implicit_type = nullptr; @@ -1926,7 +1940,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) { if (implicit_type->id == TypeTableEntryIdUnreachable) { add_node_error(g, source_node, buf_sprintf("variable initialization is unreachable")); implicit_type = g->builtin_types.entry_invalid; - } else if ((!is_const || is_export) && + } else if ((!is_const || linkage == VarLinkageExternal) && (implicit_type->id == TypeTableEntryIdNumLitFloat || implicit_type->id == TypeTableEntryIdNumLitInt)) { @@ -1940,7 +1954,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) { implicit_type = g->builtin_types.entry_invalid; } assert(implicit_type->id == TypeTableEntryIdInvalid || init_value->value.special != ConstValSpecialRuntime); - } else if (!is_extern) { + } else if (linkage != VarLinkageExternal) { add_node_error(g, source_node, buf_sprintf("variables must be initialized")); implicit_type = g->builtin_types.entry_invalid; } @@ -1951,7 +1965,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) { ConstExprValue *init_val = init_value ? &init_value->value : create_const_runtime(type); tld_var->var = add_variable(g, source_node, tld_var->base.parent_scope, var_decl->symbol, is_const, init_val); - tld_var->var->is_extern = is_extern; + tld_var->var->linkage = linkage; g->global_vars.append(tld_var->var); } diff --git a/src/ast_render.cpp b/src/ast_render.cpp index 1c82ef972e..4464a06376 100644 --- a/src/ast_render.cpp +++ b/src/ast_render.cpp @@ -955,7 +955,7 @@ static void ast_render_tld_var(AstRender *ar, Buf *name, TldVar *tld_var) { VariableTableEntry *var = tld_var->var; const char *visib_mod_str = visib_mod_string(tld_var->base.visib_mod); const char *const_or_var = const_or_var_string(var->src_is_const); - const char *extern_str = extern_string(var->is_extern); + const char *extern_str = extern_string(var->linkage == VarLinkageExternal); fprintf(ar->f, "%s%s%s %s", visib_mod_str, extern_str, const_or_var, buf_ptr(name)); if (var->value.type->id == TypeTableEntryIdNumLitFloat || diff --git a/src/codegen.cpp b/src/codegen.cpp index 87011ef051..c86b6ac56d 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -226,7 +226,7 @@ void codegen_set_rdynamic(CodeGen *g, bool rdynamic) { } static void render_const_val(CodeGen *g, ConstExprValue *const_val); -static void render_const_val_global(CodeGen *g, ConstExprValue *const_val); +static void render_const_val_global(CodeGen *g, ConstExprValue *const_val, bool is_export); static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) { if (fn_table_entry->llvm_value) @@ -681,7 +681,7 @@ static LLVMValueRef ir_llvm_value(CodeGen *g, IrInstruction *instruction) { // we might have to do some pointer casting here due to the way union // values are rendered with a type other than the one we expect if (handle_is_ptr(instruction->value.type)) { - render_const_val_global(g, &instruction->value); + render_const_val_global(g, &instruction->value, false); TypeTableEntry *ptr_type = get_pointer_to_type(g, instruction->value.type, true); instruction->llvm_value = LLVMBuildBitCast(g->builder, instruction->value.llvm_global, ptr_type->type_ref, ""); } else if (instruction->value.type->id == TypeTableEntryIdPointer) { @@ -2414,7 +2414,7 @@ static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *ar base_ptr = gen_const_ptr_array_recursive(g, parent_array, parent_array_index); } else { render_const_val(g, array_const_val); - render_const_val_global(g, array_const_val); + render_const_val_global(g, array_const_val, false); base_ptr = array_const_val->llvm_global; } TypeTableEntry *usize = g->builtin_types.entry_usize; @@ -2562,16 +2562,16 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) { return fn_llvm_value(g, const_val->data.x_fn); case TypeTableEntryIdPointer: { - render_const_val_global(g, const_val); + render_const_val_global(g, const_val, false); size_t index = const_val->data.x_ptr.index; ConstExprValue *base_ptr = const_val->data.x_ptr.base_ptr; if (base_ptr) { if (index == SIZE_MAX) { render_const_val(g, base_ptr); - render_const_val_global(g, base_ptr); + render_const_val_global(g, base_ptr, false); ConstExprValue *other_val = base_ptr; const_val->llvm_value = LLVMConstBitCast(other_val->llvm_global, const_val->type->type_ref); - render_const_val_global(g, const_val); + render_const_val_global(g, const_val, false); return const_val->llvm_value; } else { ConstExprValue *array_const_val = base_ptr; @@ -2581,19 +2581,19 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) { TypeTableEntry *usize = g->builtin_types.entry_usize; const_val->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref), const_val->type->type_ref); - render_const_val_global(g, const_val); + render_const_val_global(g, const_val, false); return const_val->llvm_value; } LLVMValueRef uncasted_ptr_val = gen_const_ptr_array_recursive(g, array_const_val, index); LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref); const_val->llvm_value = ptr_val; - render_const_val_global(g, const_val); + render_const_val_global(g, const_val, false); return ptr_val; } } else { TypeTableEntry *usize = g->builtin_types.entry_usize; const_val->llvm_value = LLVMConstIntToPtr(LLVMConstInt(usize->type_ref, index, false), const_val->type->type_ref); - render_const_val_global(g, const_val); + render_const_val_global(g, const_val, false); return const_val->llvm_value; } } @@ -2648,11 +2648,11 @@ static void render_const_val(CodeGen *g, ConstExprValue *const_val) { LLVMSetInitializer(const_val->llvm_global, const_val->llvm_value); } -static void render_const_val_global(CodeGen *g, ConstExprValue *const_val) { +static void render_const_val_global(CodeGen *g, ConstExprValue *const_val, bool is_export) { if (!const_val->llvm_global) { LLVMTypeRef type_ref = const_val->llvm_value ? LLVMTypeOf(const_val->llvm_value) : const_val->type->type_ref; LLVMValueRef global_value = LLVMAddGlobal(g->module, type_ref, ""); - LLVMSetLinkage(global_value, LLVMInternalLinkage); + LLVMSetLinkage(global_value, is_export ? LLVMExternalLinkage : LLVMInternalLinkage); LLVMSetGlobalConstant(global_value, true); LLVMSetUnnamedAddr(global_value, true); @@ -2827,15 +2827,16 @@ static void do_code_gen(CodeGen *g) { assert(var->decl_node); LLVMValueRef global_value; - if (var->is_extern) { + if (var->linkage == VarLinkageExternal) { global_value = LLVMAddGlobal(g->module, var->value.type->type_ref, buf_ptr(&var->name)); // TODO debug info for the extern variable LLVMSetLinkage(global_value, LLVMExternalLinkage); } else { + bool is_export = (var->linkage == VarLinkageExport); render_const_val(g, &var->value); - render_const_val_global(g, &var->value); + render_const_val_global(g, &var->value, is_export); global_value = var->value.llvm_global; // TODO debug info for function pointers if (var->gen_is_const && var->value.type->id != TypeTableEntryIdFn) { diff --git a/src/parseh.cpp b/src/parseh.cpp index 9a83e0d6b1..01dd6a7cf6 100644 --- a/src/parseh.cpp +++ b/src/parseh.cpp @@ -1090,7 +1090,7 @@ static void visit_var_decl(Context *c, const VarDecl *var_decl) { if (is_extern) { TldVar *tld_var = create_global_var(c, name, create_const_runtime(var_type), is_const); - tld_var->var->is_extern = true; + tld_var->var->linkage = VarLinkageExternal; add_global(c, &tld_var->base); return; } |
