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 {...@@ -1278,7 +1278,12 @@ struct CodeGen {
1278 ConstExprValue const_void_val;1278 ConstExprValue const_void_val;
1279};1279};
12801280
1281// TODO after merging IR branch, we can probably delete some of these fields1281enum VarLinkage {
1282 VarLinkageInternal,
1283 VarLinkageExport,
1284 VarLinkageExternal,
1285};
1286
1282struct VariableTableEntry {1287struct VariableTableEntry {
1283 Buf name;1288 Buf name;
1284 ConstExprValue value;1289 ConstExprValue value;
...@@ -1297,7 +1302,7 @@ struct VariableTableEntry {...@@ -1297,7 +1302,7 @@ struct VariableTableEntry {
1297 bool shadowable;1302 bool shadowable;
1298 size_t mem_slot_index;1303 size_t mem_slot_index;
1299 size_t ref_count;1304 size_t ref_count;
1300 bool is_extern;1305 VarLinkage linkage;
1301};1306};
13021307
1303struct ErrorTableEntry {1308struct ErrorTableEntry {
src/analyze.cpp+17-3
...@@ -1913,6 +1913,20 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {...@@ -1913,6 +1913,20 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
19131913
1914 AstNode *source_node = tld_var->base.source_node;1914 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
1916 IrInstruction *init_value = nullptr;1930 IrInstruction *init_value = nullptr;
19171931
1918 TypeTableEntry *implicit_type = nullptr;1932 TypeTableEntry *implicit_type = nullptr;
...@@ -1926,7 +1940,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {...@@ -1926,7 +1940,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
1926 if (implicit_type->id == TypeTableEntryIdUnreachable) {1940 if (implicit_type->id == TypeTableEntryIdUnreachable) {
1927 add_node_error(g, source_node, buf_sprintf("variable initialization is unreachable"));1941 add_node_error(g, source_node, buf_sprintf("variable initialization is unreachable"));
1928 implicit_type = g->builtin_types.entry_invalid;1942 implicit_type = g->builtin_types.entry_invalid;
1929 } else if ((!is_const || is_export) &&1943 } else if ((!is_const || linkage == VarLinkageExternal) &&
1930 (implicit_type->id == TypeTableEntryIdNumLitFloat ||1944 (implicit_type->id == TypeTableEntryIdNumLitFloat ||
1931 implicit_type->id == TypeTableEntryIdNumLitInt))1945 implicit_type->id == TypeTableEntryIdNumLitInt))
1932 {1946 {
...@@ -1940,7 +1954,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {...@@ -1940,7 +1954,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
1940 implicit_type = g->builtin_types.entry_invalid;1954 implicit_type = g->builtin_types.entry_invalid;
1941 }1955 }
1942 assert(implicit_type->id == TypeTableEntryIdInvalid || init_value->value.special != ConstValSpecialRuntime);1956 assert(implicit_type->id == TypeTableEntryIdInvalid || init_value->value.special != ConstValSpecialRuntime);
1943 } else if (!is_extern) {1957 } else if (linkage != VarLinkageExternal) {
1944 add_node_error(g, source_node, buf_sprintf("variables must be initialized"));1958 add_node_error(g, source_node, buf_sprintf("variables must be initialized"));
1945 implicit_type = g->builtin_types.entry_invalid;1959 implicit_type = g->builtin_types.entry_invalid;
1946 }1960 }
...@@ -1951,7 +1965,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {...@@ -1951,7 +1965,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
1951 ConstExprValue *init_val = init_value ? &init_value->value : create_const_runtime(type);1965 ConstExprValue *init_val = init_value ? &init_value->value : create_const_runtime(type);
19521966
1953 tld_var->var = add_variable(g, source_node, tld_var->base.parent_scope, var_decl->symbol, is_const, init_val);1967 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
1956 g->global_vars.append(tld_var->var);1970 g->global_vars.append(tld_var->var);
1957}1971}
src/ast_render.cpp+1-1
...@@ -955,7 +955,7 @@ static void ast_render_tld_var(AstRender *ar, Buf *name, TldVar *tld_var) {...@@ -955,7 +955,7 @@ static void ast_render_tld_var(AstRender *ar, Buf *name, TldVar *tld_var) {
955 VariableTableEntry *var = tld_var->var;955 VariableTableEntry *var = tld_var->var;
956 const char *visib_mod_str = visib_mod_string(tld_var->base.visib_mod);956 const char *visib_mod_str = visib_mod_string(tld_var->base.visib_mod);
957 const char *const_or_var = const_or_var_string(var->src_is_const);957 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);
959 fprintf(ar->f, "%s%s%s %s", visib_mod_str, extern_str, const_or_var, buf_ptr(name));959 fprintf(ar->f, "%s%s%s %s", visib_mod_str, extern_str, const_or_var, buf_ptr(name));
960960
961 if (var->value.type->id == TypeTableEntryIdNumLitFloat ||961 if (var->value.type->id == TypeTableEntryIdNumLitFloat ||
src/codegen.cpp+14-13
...@@ -226,7 +226,7 @@ void codegen_set_rdynamic(CodeGen *g, bool rdynamic) {...@@ -226,7 +226,7 @@ void codegen_set_rdynamic(CodeGen *g, bool rdynamic) {
226}226}
227227
228static void render_const_val(CodeGen *g, ConstExprValue *const_val);228static 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
231static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) {231static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) {
232 if (fn_table_entry->llvm_value)232 if (fn_table_entry->llvm_value)
...@@ -681,7 +681,7 @@ static LLVMValueRef ir_llvm_value(CodeGen *g, IrInstruction *instruction) {...@@ -681,7 +681,7 @@ static LLVMValueRef ir_llvm_value(CodeGen *g, IrInstruction *instruction) {
681 // we might have to do some pointer casting here due to the way union681 // we might have to do some pointer casting here due to the way union
682 // values are rendered with a type other than the one we expect682 // values are rendered with a type other than the one we expect
683 if (handle_is_ptr(instruction->value.type)) {683 if (handle_is_ptr(instruction->value.type)) {
684 render_const_val_global(g, &instruction->value);684 render_const_val_global(g, &instruction->value, false);
685 TypeTableEntry *ptr_type = get_pointer_to_type(g, instruction->value.type, true);685 TypeTableEntry *ptr_type = get_pointer_to_type(g, instruction->value.type, true);
686 instruction->llvm_value = LLVMBuildBitCast(g->builder, instruction->value.llvm_global, ptr_type->type_ref, "");686 instruction->llvm_value = LLVMBuildBitCast(g->builder, instruction->value.llvm_global, ptr_type->type_ref, "");
687 } else if (instruction->value.type->id == TypeTableEntryIdPointer) {687 } else if (instruction->value.type->id == TypeTableEntryIdPointer) {
...@@ -2414,7 +2414,7 @@ static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *ar...@@ -2414,7 +2414,7 @@ static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *ar
2414 base_ptr = gen_const_ptr_array_recursive(g, parent_array, parent_array_index);2414 base_ptr = gen_const_ptr_array_recursive(g, parent_array, parent_array_index);
2415 } else {2415 } else {
2416 render_const_val(g, array_const_val);2416 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);
2418 base_ptr = array_const_val->llvm_global;2418 base_ptr = array_const_val->llvm_global;
2419 }2419 }
2420 TypeTableEntry *usize = g->builtin_types.entry_usize;2420 TypeTableEntry *usize = g->builtin_types.entry_usize;
...@@ -2562,16 +2562,16 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {...@@ -2562,16 +2562,16 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
2562 return fn_llvm_value(g, const_val->data.x_fn);2562 return fn_llvm_value(g, const_val->data.x_fn);
2563 case TypeTableEntryIdPointer:2563 case TypeTableEntryIdPointer:
2564 {2564 {
2565 render_const_val_global(g, const_val);2565 render_const_val_global(g, const_val, false);
2566 size_t index = const_val->data.x_ptr.index;2566 size_t index = const_val->data.x_ptr.index;
2567 ConstExprValue *base_ptr = const_val->data.x_ptr.base_ptr;2567 ConstExprValue *base_ptr = const_val->data.x_ptr.base_ptr;
2568 if (base_ptr) {2568 if (base_ptr) {
2569 if (index == SIZE_MAX) {2569 if (index == SIZE_MAX) {
2570 render_const_val(g, base_ptr);2570 render_const_val(g, base_ptr);
2571 render_const_val_global(g, base_ptr);2571 render_const_val_global(g, base_ptr, false);
2572 ConstExprValue *other_val = base_ptr;2572 ConstExprValue *other_val = base_ptr;
2573 const_val->llvm_value = LLVMConstBitCast(other_val->llvm_global, const_val->type->type_ref);2573 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);
2575 return const_val->llvm_value;2575 return const_val->llvm_value;
2576 } else {2576 } else {
2577 ConstExprValue *array_const_val = base_ptr;2577 ConstExprValue *array_const_val = base_ptr;
...@@ -2581,19 +2581,19 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {...@@ -2581,19 +2581,19 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
2581 TypeTableEntry *usize = g->builtin_types.entry_usize;2581 TypeTableEntry *usize = g->builtin_types.entry_usize;
2582 const_val->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref),2582 const_val->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref),
2583 const_val->type->type_ref);2583 const_val->type->type_ref);
2584 render_const_val_global(g, const_val);2584 render_const_val_global(g, const_val, false);
2585 return const_val->llvm_value;2585 return const_val->llvm_value;
2586 }2586 }
2587 LLVMValueRef uncasted_ptr_val = gen_const_ptr_array_recursive(g, array_const_val, index);2587 LLVMValueRef uncasted_ptr_val = gen_const_ptr_array_recursive(g, array_const_val, index);
2588 LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref);2588 LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref);
2589 const_val->llvm_value = ptr_val;2589 const_val->llvm_value = ptr_val;
2590 render_const_val_global(g, const_val);2590 render_const_val_global(g, const_val, false);
2591 return ptr_val;2591 return ptr_val;
2592 }2592 }
2593 } else {2593 } else {
2594 TypeTableEntry *usize = g->builtin_types.entry_usize;2594 TypeTableEntry *usize = g->builtin_types.entry_usize;
2595 const_val->llvm_value = LLVMConstIntToPtr(LLVMConstInt(usize->type_ref, index, false), const_val->type->type_ref);2595 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);
2597 return const_val->llvm_value;2597 return const_val->llvm_value;
2598 }2598 }
2599 }2599 }
...@@ -2648,11 +2648,11 @@ static void render_const_val(CodeGen *g, ConstExprValue *const_val) {...@@ -2648,11 +2648,11 @@ static void render_const_val(CodeGen *g, ConstExprValue *const_val) {
2648 LLVMSetInitializer(const_val->llvm_global, const_val->llvm_value);2648 LLVMSetInitializer(const_val->llvm_global, const_val->llvm_value);
2649}2649}
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) {
2652 if (!const_val->llvm_global) {2652 if (!const_val->llvm_global) {
2653 LLVMTypeRef type_ref = const_val->llvm_value ? LLVMTypeOf(const_val->llvm_value) : const_val->type->type_ref;2653 LLVMTypeRef type_ref = const_val->llvm_value ? LLVMTypeOf(const_val->llvm_value) : const_val->type->type_ref;
2654 LLVMValueRef global_value = LLVMAddGlobal(g->module, type_ref, "");2654 LLVMValueRef global_value = LLVMAddGlobal(g->module, type_ref, "");
2655 LLVMSetLinkage(global_value, LLVMInternalLinkage);2655 LLVMSetLinkage(global_value, is_export ? LLVMExternalLinkage : LLVMInternalLinkage);
2656 LLVMSetGlobalConstant(global_value, true);2656 LLVMSetGlobalConstant(global_value, true);
2657 LLVMSetUnnamedAddr(global_value, true);2657 LLVMSetUnnamedAddr(global_value, true);
26582658
...@@ -2827,15 +2827,16 @@ static void do_code_gen(CodeGen *g) {...@@ -2827,15 +2827,16 @@ static void do_code_gen(CodeGen *g) {
2827 assert(var->decl_node);2827 assert(var->decl_node);
28282828
2829 LLVMValueRef global_value;2829 LLVMValueRef global_value;
2830 if (var->is_extern) {2830 if (var->linkage == VarLinkageExternal) {
2831 global_value = LLVMAddGlobal(g->module, var->value.type->type_ref, buf_ptr(&var->name));2831 global_value = LLVMAddGlobal(g->module, var->value.type->type_ref, buf_ptr(&var->name));
28322832
2833 // TODO debug info for the extern variable2833 // TODO debug info for the extern variable
28342834
2835 LLVMSetLinkage(global_value, LLVMExternalLinkage);2835 LLVMSetLinkage(global_value, LLVMExternalLinkage);
2836 } else {2836 } else {
2837 bool is_export = (var->linkage == VarLinkageExport);
2837 render_const_val(g, &var->value);2838 render_const_val(g, &var->value);
2838 render_const_val_global(g, &var->value);2839 render_const_val_global(g, &var->value, is_export);
2839 global_value = var->value.llvm_global;2840 global_value = var->value.llvm_global;
2840 // TODO debug info for function pointers2841 // TODO debug info for function pointers
2841 if (var->gen_is_const && var->value.type->id != TypeTableEntryIdFn) {2842 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) {...@@ -1090,7 +1090,7 @@ static void visit_var_decl(Context *c, const VarDecl *var_decl) {
10901090
1091 if (is_extern) {1091 if (is_extern) {
1092 TldVar *tld_var = create_global_var(c, name, create_const_runtime(var_type), is_const);1092 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;
1094 add_global(c, &tld_var->base);1094 add_global(c, &tld_var->base);
1095 return;1095 return;
1096 }1096 }