Revert "Support taking extern pointers at comptime"
This reverts commit d3ebd42865
.
This caused a build failure on multiple targets.
master
parent
978a38ee40
commit
995fd7314c
|
@ -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));
|
||||
|
|
61
src/ir.cpp
61
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;
|
||||
|
|
|
@ -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",
|
||||
});
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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 };
|
|
@ -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,
|
||||
};
|
Loading…
Reference in New Issue