From 995fd7314cd230ca7c829bb478f88b1ab7efd7b4 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 24 Jul 2020 14:06:44 -0700 Subject: [PATCH] Revert "Support taking extern pointers at comptime" This reverts commit d3ebd428650748e60db70dd2171cc044855814b1. This caused a build failure on multiple targets. --- src/codegen.cpp | 70 +++++----------- src/ir.cpp | 61 ++++++-------- test/compile_errors.zig | 22 ----- test/standalone.zig | 1 - test/standalone/extern_ref/build.zig | 15 ---- test/standalone/extern_ref/main.zig | 120 --------------------------- test/standalone/extern_ref/obj.zig | 27 ------ test/standalone/extern_ref/types.zig | 15 ---- 8 files changed, 47 insertions(+), 284 deletions(-) delete mode 100644 test/standalone/extern_ref/build.zig delete mode 100644 test/standalone/extern_ref/main.zig delete mode 100644 test/standalone/extern_ref/obj.zig delete mode 100644 test/standalone/extern_ref/types.zig diff --git a/src/codegen.cpp b/src/codegen.cpp index 246ecb4369..3f3d80d51d 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -7754,13 +7754,6 @@ static LLVMValueRef gen_const_val(CodeGen *g, ZigValue *const_val, const char *n } static void render_const_val(CodeGen *g, ZigValue *const_val, const char *name) { - if (const_val->special == ConstValSpecialRuntime) { - // `const_val` refers to an extern variable. Don't generate an `LLVMValueRef` for - // the variable. We shouldn't call `LLVMSetInitializer` on it either. - assert(const_val->llvm_global); - return; - } - if (!const_val->llvm_value) const_val->llvm_value = gen_const_val(g, const_val, name); @@ -7769,13 +7762,6 @@ static void render_const_val(CodeGen *g, ZigValue *const_val, const char *name) } static void render_const_val_global(CodeGen *g, ZigValue *const_val, const char *name) { - if (const_val->special == ConstValSpecialRuntime) { - // `const_val` refers to an extern variable. `llvm_global` should already - // have been created by an earlier codegen pass. - assert(const_val->llvm_global); - return; - } - if (!const_val->llvm_global) { LLVMTypeRef type_ref = const_val->llvm_value ? LLVMTypeOf(const_val->llvm_value) : get_llvm_type(g, const_val->type); @@ -7905,39 +7891,6 @@ static void do_code_gen(CodeGen *g) { generate_error_name_table(g); - // Create extern variables - for (size_t i = 0; i < g->global_vars.length; i += 1) { - TldVar *tld_var = g->global_vars.at(i); - ZigVar *var = tld_var->var; - - bool externally_initialized = var->decl_node->data.variable_declaration.expr == nullptr; - if (!externally_initialized) { - continue; - } - - assert(var->decl_node->data.variable_declaration.is_extern); - const char *symbol_name = var->name; - - LLVMValueRef global_value; - LLVMValueRef existing_llvm_var = LLVMGetNamedGlobal(g->module, symbol_name); - if (existing_llvm_var) { - global_value = LLVMConstBitCast(existing_llvm_var, - LLVMPointerType(get_llvm_type(g, var->var_type), 0)); - } else { - global_value = LLVMAddGlobal(g->module, get_llvm_type(g, var->var_type), symbol_name); - // TODO debug info for the extern variable - - LLVMSetLinkage(global_value, LLVMExternalLinkage); - maybe_import_dll(g, global_value, GlobalLinkageIdStrong); - LLVMSetAlignment(global_value, var->align_bytes); - LLVMSetGlobalConstant(global_value, var->gen_is_const); - set_global_tls(g, var, global_value); - } - - var->value_ref = global_value; - var->const_value->llvm_global = global_value; - } - // Generate module level variables for (size_t i = 0; i < g->global_vars.length; i += 1) { TldVar *tld_var = g->global_vars.at(i); @@ -8003,12 +7956,28 @@ static void do_code_gen(CodeGen *g) { linkage = global_export->linkage; } + LLVMValueRef global_value; bool externally_initialized = var->decl_node->data.variable_declaration.expr == nullptr; - if (!externally_initialized) { + if (externally_initialized) { + LLVMValueRef existing_llvm_var = LLVMGetNamedGlobal(g->module, symbol_name); + if (existing_llvm_var) { + global_value = LLVMConstBitCast(existing_llvm_var, + LLVMPointerType(get_llvm_type(g, var->var_type), 0)); + } else { + global_value = LLVMAddGlobal(g->module, get_llvm_type(g, var->var_type), symbol_name); + // TODO debug info for the extern variable + + LLVMSetLinkage(global_value, to_llvm_linkage(linkage)); + maybe_import_dll(g, global_value, GlobalLinkageIdStrong); + LLVMSetAlignment(global_value, var->align_bytes); + LLVMSetGlobalConstant(global_value, var->gen_is_const); + set_global_tls(g, var, global_value); + } + } else { bool exported = (linkage != GlobalLinkageIdInternal); render_const_val(g, var->const_value, symbol_name); render_const_val_global(g, var->const_value, symbol_name); - LLVMValueRef global_value = var->const_value->llvm_global; + global_value = var->const_value->llvm_global; if (exported) { LLVMSetLinkage(global_value, to_llvm_linkage(linkage)); @@ -8028,9 +7997,10 @@ static void do_code_gen(CodeGen *g) { LLVMSetGlobalConstant(global_value, var->gen_is_const); set_global_tls(g, var, global_value); - var->value_ref = global_value; } + var->value_ref = global_value; + for (size_t export_i = 1; export_i < var->export_list.length; export_i += 1) { GlobalExport *global_export = &var->export_list.items[export_i]; LLVMAddAlias(g->module, LLVMTypeOf(var->value_ref), var->value_ref, buf_ptr(&global_export->name)); diff --git a/src/ir.cpp b/src/ir.cpp index df5a0a47df..cf8558761f 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -19894,34 +19894,30 @@ static IrInstGen *ir_get_var_ptr(IrAnalyze *ira, IrInst *source_instr, ZigVar *v IrInstGen *result = ir_build_var_ptr_gen(ira, source_instr, var); result->value->type = var_ptr_type; - bool is_local_var = !var->decl_node->data.variable_declaration.is_extern && - var->const_value->special == ConstValSpecialRuntime; - - // The address of a thread-local variable can't be resolved even by a linker because - // it's dependent on the current thread. The concept of current thread doesn't exist - // at compile time, so even if we had a symbolic (i.e., relocatable) representation - // of a pointer to a thread-local variable, there would be no ways to make use of it - // in a meaningful way. - // - // The same goes for local variables - They are stored in a stack frame, whose - // instance doesn't even exist at compile/link time. - if (!var->is_thread_local && !is_local_var) { + if (!linkage_makes_it_runtime && !var->is_thread_local && value_is_comptime(var->const_value)) { ZigValue *val = var->const_value; - - ConstPtrMut ptr_mut; - if (comptime_var_mem) { - ptr_mut = ConstPtrMutComptimeVar; - } else if (var->gen_is_const && !linkage_makes_it_runtime) { - ptr_mut = ConstPtrMutComptimeConst; - } else { - assert(!comptime_var_mem); - ptr_mut = ConstPtrMutRuntimeVar; + switch (val->special) { + case ConstValSpecialRuntime: + break; + case ConstValSpecialStatic: // fallthrough + case ConstValSpecialLazy: // fallthrough + case ConstValSpecialUndef: { + ConstPtrMut ptr_mut; + if (comptime_var_mem) { + ptr_mut = ConstPtrMutComptimeVar; + } else if (var->gen_is_const) { + ptr_mut = ConstPtrMutComptimeConst; + } else { + assert(!comptime_var_mem); + ptr_mut = ConstPtrMutRuntimeVar; + } + result->value->special = ConstValSpecialStatic; + result->value->data.x_ptr.mut = ptr_mut; + result->value->data.x_ptr.special = ConstPtrSpecialRef; + result->value->data.x_ptr.data.ref.pointee = val; + return result; + } } - result->value->special = ConstValSpecialStatic; - result->value->data.x_ptr.mut = ptr_mut; - result->value->data.x_ptr.special = ConstPtrSpecialRef; - result->value->data.x_ptr.data.ref.pointee = val; - return result; } bool in_fn_scope = (scope_fn_entry(var->parent_scope) != nullptr); @@ -22292,15 +22288,12 @@ static IrInstGen *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInst* source_ins if (type_is_invalid(struct_val->type)) return ira->codegen->invalid_inst_gen; - if (ptr_val->data.x_ptr.mut != ConstPtrMutRuntimeVar) { - // This to allow lazy values to be resolved. - if ((err = ir_resolve_const_val(ira->codegen, ira->new_irb.exec, - source_instr->source_node, struct_val, UndefOk))) - { - return ira->codegen->invalid_inst_gen; - } + // This to allow lazy values to be resolved. + if ((err = ir_resolve_const_val(ira->codegen, ira->new_irb.exec, + source_instr->source_node, struct_val, UndefOk))) + { + return ira->codegen->invalid_inst_gen; } - if (initializing && struct_val->special == ConstValSpecialUndef) { struct_val->data.x_struct.fields = alloc_const_vals_ptrs(ira->codegen, struct_type->data.structure.src_field_count); struct_val->special = ConstValSpecialStatic; diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 1ccc95c9cc..a1a261f887 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -7637,26 +7637,4 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { , &[_][]const u8{ "tmp.zig:4:9: error: expected type '*c_void', found '?*c_void'", }); - - cases.add("pointer to a local runtime `var` is not constant", - \\export fn get_ptr() *const u32 { - \\ var local_var: u32 = 42; - \\ return struct { - \\ const ptr = &local_var; - \\ }.ptr; - \\} - , &[_][]const u8{ - ":4:21: error: cannot store runtime value in compile time variable", - }); - - cases.add("pointer to a local runtime `const` is not constant", - \\export fn get_ptr(x: u32) *const u32 { - \\ const local_var: u32 = x; - \\ return struct { - \\ const ptr = &local_var; - \\ }.ptr; - \\} - , &[_][]const u8{ - ":4:21: error: cannot store runtime value in compile time variable", - }); } diff --git a/test/standalone.zig b/test/standalone.zig index ad41ba6762..d73587ccd6 100644 --- a/test/standalone.zig +++ b/test/standalone.zig @@ -19,7 +19,6 @@ pub fn addCases(cases: *tests.StandaloneContext) void { cases.addBuildFile("test/standalone/use_alias/build.zig"); cases.addBuildFile("test/standalone/brace_expansion/build.zig"); cases.addBuildFile("test/standalone/empty_env/build.zig"); - cases.addBuildFile("test/standalone/extern_ref/build.zig"); if (std.Target.current.os.tag != .wasi) { cases.addBuildFile("test/standalone/load_dynamic_library/build.zig"); } diff --git a/test/standalone/extern_ref/build.zig b/test/standalone/extern_ref/build.zig deleted file mode 100644 index 839898345a..0000000000 --- a/test/standalone/extern_ref/build.zig +++ /dev/null @@ -1,15 +0,0 @@ -const Builder = @import("std").build.Builder; - -pub fn build(b: *Builder) void { - const mode = b.standardReleaseOptions(); - - const obj = b.addStaticLibrary("obj", "obj.zig"); - obj.setBuildMode(mode); - - const main = b.addTest("main.zig"); - main.setBuildMode(mode); - main.linkLibrary(obj); - - const test_step = b.step("test", "Test it"); - test_step.dependOn(&main.step); -} diff --git a/test/standalone/extern_ref/main.zig b/test/standalone/extern_ref/main.zig deleted file mode 100644 index 52fe2d9f21..0000000000 --- a/test/standalone/extern_ref/main.zig +++ /dev/null @@ -1,120 +0,0 @@ -const std = @import("std"); -const eql = std.mem.eql; - -// These are defined in `obj.zig` -extern var global_var: usize; -extern const global_const: usize; - -const TheStruct = @import("./types.zig").TheStruct; -extern var global_var_struct: TheStruct; -extern const global_const_struct: TheStruct; - -const TheUnion = @import("./types.zig").TheUnion; -extern var global_var_union: TheUnion; -extern const global_const_union: TheUnion; - -extern var global_var_array: [4]u32; -extern const global_const_array: [4]u32; - -// Take the pointers to external entities as constant values -const p_global_var = &global_var; -const p_global_const = &global_const; - -test "access the external integers" { - std.testing.expect(p_global_var.* == 2); - std.testing.expect(p_global_const.* == 422); -} - -const p_global_var_struct = &global_var_struct; -const p_global_const_struct = &global_const_struct; - -const p_global_var_struct_val = &global_var_struct.value; -const p_global_const_struct_val = &global_const_struct.value; - -const p_global_var_struct_array = &global_var_struct.array; -const p_global_const_struct_array = &global_const_struct.array; - -const p_global_var_struct_array2 = global_var_struct.array[1..3]; -const p_global_const_struct_array2 = global_const_struct.array[1..3]; - -const p_global_var_struct_array3 = &global_var_struct.array[1]; -const p_global_const_struct_array3 = &global_const_struct.array[1]; - -test "access the external integers in a struct through comptime ptrs" { - std.testing.expect(p_global_var_struct.value == 2); - std.testing.expect(p_global_const_struct.value == 422); - - std.testing.expect(p_global_var_struct_val.* == 2); - std.testing.expect(p_global_const_struct_val.* == 422); -} - -test "access the external arrays in a struct through comptime ptrs" { - // TODO - // std.testing.expect(eql(u32, &p_global_var_struct.array, &[_]u32{1, 2, 3, 4})); - // std.testing.expect(eql(u32, &p_global_const_struct.array, &[_]u32{5, 6, 7, 8})); - - // TODO - // std.testing.expect(eql(u32, p_global_var_struct_array, &[_]u32{1, 2, 3, 4})); - // std.testing.expect(eql(u32, p_global_const_struct_array, &[_]u32{5, 6, 7, 8})); - - // TODO - // std.testing.expect(eql(u32, p_global_var_struct_array2, &[_]u32{2, 3})); - // std.testing.expect(eql(u32, p_global_const_struct_array2, &[_]u32{6, 7})); - - // TODO - // std.testing.expect(p_global_var_struct_array3.* == 2); - // std.testing.expect(p_global_const_struct_array3.* == 6); -} - -test "access the external integers with indirection through comptime ptrs" { - std.testing.expect(p_global_var_struct.p_value.* == 3); - std.testing.expect(p_global_const_struct.p_value.* == 423); -} - -const p_global_var_struct_inner_val = &global_var_struct.inner.value; -const p_global_const_struct_inner_val = &global_const_struct.inner.value; - -test "access the external integers in a nested struct through comptime ptrs" { - // TODO - // std.testing.expect(p_global_var_struct_inner_val.* == 4); - // std.testing.expect(p_global_const_struct_inner_val.* == 424); -} - -const p_global_var_union = &global_var_union; -const p_global_const_union = &global_const_union; - -const p_global_var_union_val = &global_var_union.U32; -const p_global_const_union_val = &global_const_union.U32; - -test "access the external integers in a union through comptime ptrs" { - std.testing.expect(p_global_var_union.U32 == 10); - std.testing.expect(p_global_const_union.U32 == 20); - - // TODO - // std.testing.expect(p_global_var_union_val.* == 10); - // std.testing.expect(p_global_const_union_val.* == 20); -} - -const p_global_var_array = &global_var_array; -const p_global_const_array = &global_const_array; - -const p_global_var_array2 = global_var_array[1..3]; -const p_global_const_array2 = global_const_array[1..3]; - -const p_global_var_array3 = &global_var_array[1]; -const p_global_const_array3 = &global_const_array[1]; - -test "access the external arrays through comptime ptrs" { - std.testing.expect(eql(u32, &global_var_array, &[_]u32{1, 2, 3, 4})); - std.testing.expect(eql(u32, &global_const_array, &[_]u32{5, 6, 7, 8})); - - std.testing.expect(eql(u32, p_global_var_array, &[_]u32{1, 2, 3, 4})); - std.testing.expect(eql(u32, p_global_const_array, &[_]u32{5, 6, 7, 8})); - - std.testing.expect(eql(u32, p_global_var_array2, &[_]u32{2, 3})); - std.testing.expect(eql(u32, p_global_const_array2, &[_]u32{6, 7})); - - // TODO - // std.testing.expect(p_global_var_array3.* == 2); - // std.testing.expect(p_global_const_array3.* == 6); -} diff --git a/test/standalone/extern_ref/obj.zig b/test/standalone/extern_ref/obj.zig deleted file mode 100644 index 8a44fd3a60..0000000000 --- a/test/standalone/extern_ref/obj.zig +++ /dev/null @@ -1,27 +0,0 @@ -export var global_var: usize = 2; -export const global_const: usize = 422; - -const TheStruct = @import("./types.zig").TheStruct; -export var global_var_struct = TheStruct{ - .value = 2, - .array = [_]u32{ 1, 2, 3, 4 }, - .p_value = &@as(u32, 3), - .inner = .{ .value = 4 }, -}; -export const global_const_struct = TheStruct{ - .value = 422, - .array = [_]u32{ 5, 6, 7, 8 }, - .p_value = &@as(u32, 423), - .inner = .{ .value = 424 }, -}; - -const TheUnion = @import("./types.zig").TheUnion; -export var global_var_union = TheUnion{ - .U32 = 10, -}; -export const global_const_union = TheUnion{ - .U32 = 20, -}; - -export var global_var_array = [4]u32{ 1, 2, 3, 4 }; -export const global_const_array = [4]u32{ 5, 6, 7, 8 }; diff --git a/test/standalone/extern_ref/types.zig b/test/standalone/extern_ref/types.zig deleted file mode 100644 index df8a3807b0..0000000000 --- a/test/standalone/extern_ref/types.zig +++ /dev/null @@ -1,15 +0,0 @@ -pub const TheStruct = extern struct { - value: u32, - array: [4]u32, - p_value: *const u32, - inner: InnerStruct, -}; - -pub const InnerStruct = extern struct { - value: u32, -}; - -pub const TheUnion = extern union { - U32: u32, - Bool: bool, -};