Skip to content

Commit

Permalink
Revert "Support taking extern pointers at comptime"
Browse files Browse the repository at this point in the history
This reverts commit d3ebd42.

This caused a build failure on multiple targets.
  • Loading branch information
andrewrk committed Jul 24, 2020
1 parent 978a38e commit 995fd73
Show file tree
Hide file tree
Showing 8 changed files with 47 additions and 284 deletions.
70 changes: 20 additions & 50 deletions src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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));
Expand All @@ -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));
Expand Down
61 changes: 27 additions & 34 deletions src/ir.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down
22 changes: 0 additions & 22 deletions test/compile_errors.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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",
});
}
1 change: 0 additions & 1 deletion test/standalone.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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");
}
Expand Down
15 changes: 0 additions & 15 deletions test/standalone/extern_ref/build.zig

This file was deleted.

120 changes: 0 additions & 120 deletions test/standalone/extern_ref/main.zig

This file was deleted.

27 changes: 0 additions & 27 deletions test/standalone/extern_ref/obj.zig

This file was deleted.

Loading

0 comments on commit 995fd73

Please sign in to comment.