diff options
| -rw-r--r-- | example/shared_library/mathtest.zig | 9 | ||||
| -rw-r--r-- | src/all_types.hpp | 4 | ||||
| -rw-r--r-- | src/analyze.cpp | 2 | ||||
| -rw-r--r-- | src/codegen.cpp | 22 | ||||
| -rw-r--r-- | src/ir.cpp | 64 | ||||
| -rw-r--r-- | src/link.cpp | 10 | ||||
| -rw-r--r-- | std/c/darwin.zig | 11 | ||||
| -rw-r--r-- | std/debug/index.zig | 2 | ||||
| -rw-r--r-- | std/os/index.zig | 4 | ||||
| -rw-r--r-- | test/stage1/behavior/ptrcast.zig | 8 |
10 files changed, 106 insertions, 30 deletions
diff --git a/example/shared_library/mathtest.zig b/example/shared_library/mathtest.zig index 96e41f847c..a04ec1544d 100644 --- a/example/shared_library/mathtest.zig +++ b/example/shared_library/mathtest.zig @@ -1,12 +1,3 @@ -// TODO Remove this workaround -comptime { - const builtin = @import("builtin"); - if (builtin.os == builtin.Os.macosx) { - @export("__mh_execute_header", _mh_execute_header, builtin.GlobalLinkage.Weak); - } -} -var _mh_execute_header = extern struct {x: usize}{.x = 0}; - export fn add(a: i32, b: i32) i32 { return a + b; } diff --git a/src/all_types.hpp b/src/all_types.hpp index f57c3124da..87f4c889ac 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -1853,7 +1853,9 @@ struct CodeGen { enum VarLinkage { VarLinkageInternal, - VarLinkageExport, + VarLinkageExportStrong, + VarLinkageExportWeak, + VarLinkageExportLinkOnce, VarLinkageExternal, }; diff --git a/src/analyze.cpp b/src/analyze.cpp index 37c0041314..934da61186 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -3746,7 +3746,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) { VarLinkage linkage; if (is_export) { - linkage = VarLinkageExport; + linkage = VarLinkageExportStrong; } else if (is_extern) { linkage = VarLinkageExternal; } else { diff --git a/src/codegen.cpp b/src/codegen.cpp index 9085d4ea7c..843f8cfd17 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -6421,6 +6421,22 @@ static void set_global_tls(CodeGen *g, ZigVar *var, LLVMValueRef global_value) { } } +static LLVMLinkage var_linkage_to_llvm(VarLinkage var_linkage) { + switch (var_linkage) { + case VarLinkageInternal: + return LLVMInternalLinkage; + case VarLinkageExportStrong: + return LLVMExternalLinkage; + case VarLinkageExportWeak: + return LLVMWeakODRLinkage; + case VarLinkageExportLinkOnce: + return LLVMLinkOnceODRLinkage; + case VarLinkageExternal: + return LLVMExternalLinkage; + } + zig_unreachable(); +} + static void do_code_gen(CodeGen *g) { assert(!g->errors.length); @@ -6501,21 +6517,21 @@ static void do_code_gen(CodeGen *g) { global_value = LLVMAddGlobal(g->module, var->var_type->type_ref, buf_ptr(&var->name)); // TODO debug info for the extern variable - LLVMSetLinkage(global_value, LLVMExternalLinkage); + LLVMSetLinkage(global_value, var_linkage_to_llvm(var->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 = (var->linkage == VarLinkageExport); + bool exported = (var->linkage != VarLinkageInternal); const char *mangled_name = buf_ptr(get_mangled_name(g, &var->name, exported)); render_const_val(g, var->const_value, mangled_name); render_const_val_global(g, var->const_value, mangled_name); global_value = var->const_value->global_refs->llvm_global; if (exported) { - LLVMSetLinkage(global_value, LLVMExternalLinkage); + LLVMSetLinkage(global_value, var_linkage_to_llvm(var->linkage)); maybe_export_dll(g, global_value, GlobalLinkageIdStrong); } if (tld_var->section_name) { diff --git a/src/ir.cpp b/src/ir.cpp index d51df52373..5c5893cdd5 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -13133,6 +13133,20 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, return ir_build_var_decl_gen(ira, &decl_var_instruction->base, var, casted_init_value); } +static VarLinkage global_linkage_to_var_linkage(GlobalLinkageId id) { + switch (id) { + case GlobalLinkageIdStrong: + return VarLinkageExportStrong; + case GlobalLinkageIdWeak: + return VarLinkageExportWeak; + case GlobalLinkageIdLinkOnce: + return VarLinkageExportLinkOnce; + case GlobalLinkageIdInternal: + return VarLinkageInternal; + } + zig_unreachable(); +} + static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructionExport *instruction) { IrInstruction *name = instruction->name->child; Buf *symbol_name = ir_resolve_str(ira, name); @@ -13161,6 +13175,7 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio add_error_note(ira->codegen, msg, other_export_node, buf_sprintf("other symbol is here")); } + bool want_var_export = false; switch (target->value.type->id) { case ZigTypeIdInvalid: case ZigTypeIdUnreachable: @@ -13196,6 +13211,8 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio ErrorMsg *msg = ir_add_error(ira, target, buf_sprintf("exported struct value must be declared extern")); add_error_note(ira->codegen, msg, target->value.type->data.structure.decl_node, buf_sprintf("declared here")); + } else { + want_var_export = true; } break; case ZigTypeIdUnion: @@ -13203,6 +13220,8 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio ErrorMsg *msg = ir_add_error(ira, target, buf_sprintf("exported union value must be declared extern")); add_error_note(ira->codegen, msg, target->value.type->data.unionation.decl_node, buf_sprintf("declared here")); + } else { + want_var_export = true; } break; case ZigTypeIdEnum: @@ -13210,6 +13229,8 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio ErrorMsg *msg = ir_add_error(ira, target, buf_sprintf("exported enum value must be declared extern")); add_error_note(ira->codegen, msg, target->value.type->data.enumeration.decl_node, buf_sprintf("declared here")); + } else { + want_var_export = true; } break; case ZigTypeIdMetaType: { @@ -13299,6 +13320,16 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio break; } + // TODO audit the various ways to use @export + if (want_var_export && target->id == IrInstructionIdLoadPtr) { + IrInstructionLoadPtr *load_ptr = reinterpret_cast<IrInstructionLoadPtr *>(target); + if (load_ptr->ptr->id == IrInstructionIdVarPtr) { + IrInstructionVarPtr *var_ptr = reinterpret_cast<IrInstructionVarPtr *>(load_ptr->ptr); + ZigVar *var = var_ptr->var; + var->linkage = global_linkage_to_var_linkage(global_linkage_id); + } + } + return ir_const_void(ira, &instruction->base); } @@ -13586,9 +13617,16 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, if (var->var_type == nullptr || type_is_invalid(var->var_type)) return ira->codegen->invalid_instruction; + ConstExprValue *mem_slot = nullptr; + bool comptime_var_mem = ir_get_var_is_comptime(var); + bool linkage_makes_it_runtime = var->linkage == VarLinkageExternal; + bool is_const = var->src_is_const; + bool is_volatile = false; + + if (linkage_makes_it_runtime) + goto no_mem_slot; - ConstExprValue *mem_slot = nullptr; if (var->const_value->special == ConstValSpecialStatic) { mem_slot = var->const_value; } else { @@ -13602,8 +13640,6 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, } } - bool is_const = var->src_is_const; - bool is_volatile = false; if (mem_slot != nullptr) { switch (mem_slot->special) { case ConstValSpecialRuntime: @@ -20679,6 +20715,13 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_ ir_add_error(ira, source_instr, buf_sprintf("cast discards const qualifier")); return ira->codegen->invalid_instruction; } + uint32_t src_align_bytes; + if ((err = resolve_ptr_align(ira, src_type, &src_align_bytes))) + return ira->codegen->invalid_instruction; + + uint32_t dest_align_bytes; + if ((err = resolve_ptr_align(ira, dest_type, &dest_align_bytes))) + return ira->codegen->invalid_instruction; if (instr_is_comptime(ptr)) { bool dest_allows_addr_zero = ptr_allows_addr_zero(dest_type); @@ -20701,16 +20744,15 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_ IrInstruction *result = ir_const(ira, source_instr, dest_type); copy_const_val(&result->value, val, false); result->value.type = dest_type; - return result; - } - uint32_t src_align_bytes; - if ((err = resolve_ptr_align(ira, src_type, &src_align_bytes))) - return ira->codegen->invalid_instruction; + // Keep the bigger alignment, it can only help- + // unless the target is zero bits. + if (src_align_bytes > dest_align_bytes && type_has_bits(dest_type)) { + result = ir_align_cast(ira, result, src_align_bytes, false); + } - uint32_t dest_align_bytes; - if ((err = resolve_ptr_align(ira, dest_type, &dest_align_bytes))) - return ira->codegen->invalid_instruction; + return result; + } if (dest_align_bytes > src_align_bytes) { ErrorMsg *msg = ir_add_error(ira, source_instr, buf_sprintf("cast increases pointer alignment")); diff --git a/src/link.cpp b/src/link.cpp index 956e5b6bfc..f6f0c0ffcd 100644 --- a/src/link.cpp +++ b/src/link.cpp @@ -899,7 +899,11 @@ static void construct_linker_job_macho(LinkJob *lj) { lj->args.append("-ios_simulator_version_min"); break; } - lj->args.append(buf_ptr(buf_sprintf("%d.%d.%d", platform.major, platform.minor, platform.micro))); + Buf *version_string = buf_sprintf("%d.%d.%d", platform.major, platform.minor, platform.micro); + lj->args.append(buf_ptr(version_string)); + + lj->args.append("-sdk_version"); + lj->args.append(buf_ptr(version_string)); if (g->out_type == OutTypeExe) { @@ -920,7 +924,9 @@ static void construct_linker_job_macho(LinkJob *lj) { add_rpath(lj, &g->output_file_path); if (shared) { - lj->args.append("-headerpad_max_install_names"); + if (g->system_linker_hack) { + lj->args.append("-headerpad_max_install_names"); + } } else if (g->is_static) { lj->args.append("-lcrt0.o"); } else { diff --git a/std/c/darwin.zig b/std/c/darwin.zig index 4f0ea4a02b..940d949985 100644 --- a/std/c/darwin.zig +++ b/std/c/darwin.zig @@ -36,11 +36,20 @@ pub extern "c" fn sysctlnametomib(name: [*]const u8, mibp: ?*c_int, sizep: ?*usi pub extern "c" fn bind(socket: c_int, address: ?*const sockaddr, address_len: socklen_t) c_int; pub extern "c" fn socket(domain: c_int, type: c_int, protocol: c_int) c_int; +const mach_hdr = if (@sizeOf(usize) == 8) mach_header_64 else mach_header; + /// The value of the link editor defined symbol _MH_EXECUTE_SYM is the address /// of the mach header in a Mach-O executable file type. It does not appear in /// any file type other than a MH_EXECUTE file type. The type of the symbol is /// absolute as the header is not part of any section. -pub extern "c" var _mh_execute_header: if (@sizeOf(usize) == 8) mach_header_64 else mach_header; +/// This symbol is populated when linking the system's libc, which is guaranteed +/// on this operating system. However when building object files or libraries, +/// the system libc won't be linked until the final executable. So we +/// export a weak symbol here, to be overridden by the real one. +pub extern "c" var _mh_execute_header: mach_hdr = undefined; +comptime { + @export("__mh_execute_header", _mh_execute_header, @import("builtin").GlobalLinkage.Weak); +} pub const mach_header_64 = macho.mach_header_64; pub const mach_header = macho.mach_header; diff --git a/std/debug/index.zig b/std/debug/index.zig index b8ea7e7f84..1d93e0227e 100644 --- a/std/debug/index.zig +++ b/std/debug/index.zig @@ -574,7 +574,7 @@ fn machoSearchSymbols(symbols: []const MachoSymbol, address: usize) ?*const Mach } fn printSourceAtAddressMacOs(di: *DebugInfo, out_stream: var, address: usize, tty_color: bool) !void { - const base_addr = @ptrToInt(&std.c._mh_execute_header); + const base_addr = std.os.getBaseAddress(); const adjusted_addr = 0x100000000 + (address - base_addr); const symbol = machoSearchSymbols(di.symbols, adjusted_addr) orelse { diff --git a/std/os/index.zig b/std/os/index.zig index 5d749479de..148f4ebe06 100644 --- a/std/os/index.zig +++ b/std/os/index.zig @@ -701,7 +701,9 @@ pub fn getBaseAddress() usize { const phdr = linuxGetAuxVal(std.elf.AT_PHDR); return phdr - @sizeOf(std.elf.Ehdr); }, - builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => return @ptrToInt(&std.c._mh_execute_header), + builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => { + return @ptrToInt(&std.c._mh_execute_header); + }, builtin.Os.windows => return @ptrToInt(windows.GetModuleHandleW(null)), else => @compileError("Unsupported OS"), } diff --git a/test/stage1/behavior/ptrcast.zig b/test/stage1/behavior/ptrcast.zig index 3787382aea..c83b2f7327 100644 --- a/test/stage1/behavior/ptrcast.zig +++ b/test/stage1/behavior/ptrcast.zig @@ -50,3 +50,11 @@ const Bytes = struct { return res; } }; + +test "comptime ptrcast keeps larger alignment" { + comptime { + const a: u32 = 1234; + const p = @ptrCast([*]const u8, &a); + std.debug.assert(@typeOf(p) == [*]align(@alignOf(u32)) const u8); + } +} |
