authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-02-03 11:59:56-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-02-03 11:59:56-05:00
logaae168550fa3d8b21478deb7198513dad8cc0b37
tree8e5f735f62abae03ef28d023d9c231b6541d706e
parent71d335e5ccc5c7c37ac40debf78ad3aa096b22d3

exported global variables get emitted as external in LLVM


5 files changed, 40 insertions(+), 20 deletions(-)

src/all_types.hpp+7-2
......@@ -1278,7 +1278,12 @@ struct CodeGen {
12781278 ConstExprValue const_void_val;
12791279};
12801280
1281// TODO after merging IR branch, we can probably delete some of these fields
1281enum VarLinkage {
1282 VarLinkageInternal,
1283 VarLinkageExport,
1284 VarLinkageExternal,
1285};
1286
12821287struct VariableTableEntry {
12831288 Buf name;
12841289 ConstExprValue value;
......@@ -1297,7 +1302,7 @@ struct VariableTableEntry {
12971302 bool shadowable;
12981303 size_t mem_slot_index;
12991304 size_t ref_count;
1300 bool is_extern;
1305 VarLinkage linkage;
13011306};
13021307
13031308struct ErrorTableEntry {
src/analyze.cpp+17-3
......@@ -1913,6 +1913,20 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
19131913
19141914 AstNode *source_node = tld_var->base.source_node;
19151915
1916 if (is_export && is_extern) {
1917 add_node_error(g, source_node, buf_sprintf("variable is both export and extern"));
1918 }
1919
1920 VarLinkage linkage;
1921 if (is_export) {
1922 linkage = VarLinkageExport;
1923 } else if (is_extern) {
1924 linkage = VarLinkageExternal;
1925 } else {
1926 linkage = VarLinkageInternal;
1927 }
1928
1929
19161930 IrInstruction *init_value = nullptr;
19171931
19181932 TypeTableEntry *implicit_type = nullptr;
......@@ -1926,7 +1940,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
19261940 if (implicit_type->id == TypeTableEntryIdUnreachable) {
19271941 add_node_error(g, source_node, buf_sprintf("variable initialization is unreachable"));
19281942 implicit_type = g->builtin_types.entry_invalid;
1929 } else if ((!is_const || is_export) &&
1943 } else if ((!is_const || linkage == VarLinkageExternal) &&
19301944 (implicit_type->id == TypeTableEntryIdNumLitFloat ||
19311945 implicit_type->id == TypeTableEntryIdNumLitInt))
19321946 {
......@@ -1940,7 +1954,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
19401954 implicit_type = g->builtin_types.entry_invalid;
19411955 }
19421956 assert(implicit_type->id == TypeTableEntryIdInvalid || init_value->value.special != ConstValSpecialRuntime);
1943 } else if (!is_extern) {
1957 } else if (linkage != VarLinkageExternal) {
19441958 add_node_error(g, source_node, buf_sprintf("variables must be initialized"));
19451959 implicit_type = g->builtin_types.entry_invalid;
19461960 }
......@@ -1951,7 +1965,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
19511965 ConstExprValue *init_val = init_value ? &init_value->value : create_const_runtime(type);
19521966
19531967 tld_var->var = add_variable(g, source_node, tld_var->base.parent_scope, var_decl->symbol, is_const, init_val);
1954 tld_var->var->is_extern = is_extern;
1968 tld_var->var->linkage = linkage;
19551969
19561970 g->global_vars.append(tld_var->var);
19571971}
src/ast_render.cpp+1-1
......@@ -955,7 +955,7 @@ static void ast_render_tld_var(AstRender *ar, Buf *name, TldVar *tld_var) {
955955 VariableTableEntry *var = tld_var->var;
956956 const char *visib_mod_str = visib_mod_string(tld_var->base.visib_mod);
957957 const char *const_or_var = const_or_var_string(var->src_is_const);
958 const char *extern_str = extern_string(var->is_extern);
958 const char *extern_str = extern_string(var->linkage == VarLinkageExternal);
959959 fprintf(ar->f, "%s%s%s %s", visib_mod_str, extern_str, const_or_var, buf_ptr(name));
960960
961961 if (var->value.type->id == TypeTableEntryIdNumLitFloat ||
src/codegen.cpp+14-13
......@@ -226,7 +226,7 @@ void codegen_set_rdynamic(CodeGen *g, bool rdynamic) {
226226}
227227
228228static void render_const_val(CodeGen *g, ConstExprValue *const_val);
229static void render_const_val_global(CodeGen *g, ConstExprValue *const_val);
229static void render_const_val_global(CodeGen *g, ConstExprValue *const_val, bool is_export);
230230
231231static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) {
232232 if (fn_table_entry->llvm_value)
......@@ -681,7 +681,7 @@ static LLVMValueRef ir_llvm_value(CodeGen *g, IrInstruction *instruction) {
681681 // we might have to do some pointer casting here due to the way union
682682 // values are rendered with a type other than the one we expect
683683 if (handle_is_ptr(instruction->value.type)) {
684 render_const_val_global(g, &instruction->value);
684 render_const_val_global(g, &instruction->value, false);
685685 TypeTableEntry *ptr_type = get_pointer_to_type(g, instruction->value.type, true);
686686 instruction->llvm_value = LLVMBuildBitCast(g->builder, instruction->value.llvm_global, ptr_type->type_ref, "");
687687 } else if (instruction->value.type->id == TypeTableEntryIdPointer) {
......@@ -2414,7 +2414,7 @@ static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *ar
24142414 base_ptr = gen_const_ptr_array_recursive(g, parent_array, parent_array_index);
24152415 } else {
24162416 render_const_val(g, array_const_val);
2417 render_const_val_global(g, array_const_val);
2417 render_const_val_global(g, array_const_val, false);
24182418 base_ptr = array_const_val->llvm_global;
24192419 }
24202420 TypeTableEntry *usize = g->builtin_types.entry_usize;
......@@ -2562,16 +2562,16 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
25622562 return fn_llvm_value(g, const_val->data.x_fn);
25632563 case TypeTableEntryIdPointer:
25642564 {
2565 render_const_val_global(g, const_val);
2565 render_const_val_global(g, const_val, false);
25662566 size_t index = const_val->data.x_ptr.index;
25672567 ConstExprValue *base_ptr = const_val->data.x_ptr.base_ptr;
25682568 if (base_ptr) {
25692569 if (index == SIZE_MAX) {
25702570 render_const_val(g, base_ptr);
2571 render_const_val_global(g, base_ptr);
2571 render_const_val_global(g, base_ptr, false);
25722572 ConstExprValue *other_val = base_ptr;
25732573 const_val->llvm_value = LLVMConstBitCast(other_val->llvm_global, const_val->type->type_ref);
2574 render_const_val_global(g, const_val);
2574 render_const_val_global(g, const_val, false);
25752575 return const_val->llvm_value;
25762576 } else {
25772577 ConstExprValue *array_const_val = base_ptr;
......@@ -2581,19 +2581,19 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
25812581 TypeTableEntry *usize = g->builtin_types.entry_usize;
25822582 const_val->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref),
25832583 const_val->type->type_ref);
2584 render_const_val_global(g, const_val);
2584 render_const_val_global(g, const_val, false);
25852585 return const_val->llvm_value;
25862586 }
25872587 LLVMValueRef uncasted_ptr_val = gen_const_ptr_array_recursive(g, array_const_val, index);
25882588 LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref);
25892589 const_val->llvm_value = ptr_val;
2590 render_const_val_global(g, const_val);
2590 render_const_val_global(g, const_val, false);
25912591 return ptr_val;
25922592 }
25932593 } else {
25942594 TypeTableEntry *usize = g->builtin_types.entry_usize;
25952595 const_val->llvm_value = LLVMConstIntToPtr(LLVMConstInt(usize->type_ref, index, false), const_val->type->type_ref);
2596 render_const_val_global(g, const_val);
2596 render_const_val_global(g, const_val, false);
25972597 return const_val->llvm_value;
25982598 }
25992599 }
......@@ -2648,11 +2648,11 @@ static void render_const_val(CodeGen *g, ConstExprValue *const_val) {
26482648 LLVMSetInitializer(const_val->llvm_global, const_val->llvm_value);
26492649}
26502650
2651static void render_const_val_global(CodeGen *g, ConstExprValue *const_val) {
2651static void render_const_val_global(CodeGen *g, ConstExprValue *const_val, bool is_export) {
26522652 if (!const_val->llvm_global) {
26532653 LLVMTypeRef type_ref = const_val->llvm_value ? LLVMTypeOf(const_val->llvm_value) : const_val->type->type_ref;
26542654 LLVMValueRef global_value = LLVMAddGlobal(g->module, type_ref, "");
2655 LLVMSetLinkage(global_value, LLVMInternalLinkage);
2655 LLVMSetLinkage(global_value, is_export ? LLVMExternalLinkage : LLVMInternalLinkage);
26562656 LLVMSetGlobalConstant(global_value, true);
26572657 LLVMSetUnnamedAddr(global_value, true);
26582658
......@@ -2827,15 +2827,16 @@ static void do_code_gen(CodeGen *g) {
28272827 assert(var->decl_node);
28282828
28292829 LLVMValueRef global_value;
2830 if (var->is_extern) {
2830 if (var->linkage == VarLinkageExternal) {
28312831 global_value = LLVMAddGlobal(g->module, var->value.type->type_ref, buf_ptr(&var->name));
28322832
28332833 // TODO debug info for the extern variable
28342834
28352835 LLVMSetLinkage(global_value, LLVMExternalLinkage);
28362836 } else {
2837 bool is_export = (var->linkage == VarLinkageExport);
28372838 render_const_val(g, &var->value);
2838 render_const_val_global(g, &var->value);
2839 render_const_val_global(g, &var->value, is_export);
28392840 global_value = var->value.llvm_global;
28402841 // TODO debug info for function pointers
28412842 if (var->gen_is_const && var->value.type->id != TypeTableEntryIdFn) {
src/parseh.cpp+1-1
......@@ -1090,7 +1090,7 @@ static void visit_var_decl(Context *c, const VarDecl *var_decl) {
10901090
10911091 if (is_extern) {
10921092 TldVar *tld_var = create_global_var(c, name, create_const_runtime(var_type), is_const);
1093 tld_var->var->is_extern = true;
1093 tld_var->var->linkage = VarLinkageExternal;
10941094 add_global(c, &tld_var->base);
10951095 return;
10961096 }