diff options
| author | Jacob Young <jacobly0@users.noreply.github.com> | 2025-06-04 21:45:31 -0400 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2025-06-06 23:42:14 -0700 |
| commit | 0bf8617d963dc432ed0204b10285cc414becf2fd (patch) | |
| tree | b4a28f10bd66183cd949e6f0fbb4a786bfc1aa04 /src/codegen | |
| parent | 178ee8aef1b9f765da916f3e1e4cab66437f8e0a (diff) | |
| download | zig-0bf8617d963dc432ed0204b10285cc414becf2fd.tar.gz zig-0bf8617d963dc432ed0204b10285cc414becf2fd.zip | |
x86_64: add support for pie executables
Diffstat (limited to 'src/codegen')
| -rw-r--r-- | src/codegen/c.zig | 34 | ||||
| -rw-r--r-- | src/codegen/llvm.zig | 123 |
2 files changed, 95 insertions, 62 deletions
diff --git a/src/codegen/c.zig b/src/codegen/c.zig index c68abc06ce..3b8ab52982 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -2255,19 +2255,30 @@ pub const DeclGen = struct { fn renderFwdDecl( dg: *DeclGen, nav_index: InternPool.Nav.Index, - flags: struct { - is_extern: bool, + flags: packed struct { is_const: bool, is_threadlocal: bool, - is_weak_linkage: bool, + linkage: std.builtin.GlobalLinkage, + visibility: std.builtin.SymbolVisibility, }, ) !void { const zcu = dg.pt.zcu; const ip = &zcu.intern_pool; const nav = ip.getNav(nav_index); const fwd = dg.fwdDeclWriter(); - try fwd.writeAll(if (flags.is_extern) "zig_extern " else "static "); - if (flags.is_weak_linkage) try fwd.writeAll("zig_weak_linkage "); + try fwd.writeAll(switch (flags.linkage) { + .internal => "static ", + .strong, .weak, .link_once => "zig_extern ", + }); + switch (flags.linkage) { + .internal, .strong => {}, + .weak => try fwd.writeAll("zig_weak_linkage "), + .link_once => return dg.fail("TODO: CBE: implement linkonce linkage?", .{}), + } + switch (flags.linkage) { + .internal => {}, + .strong, .weak, .link_once => try fwd.print("zig_visibility({s}) ", .{@tagName(flags.visibility)}), + } if (flags.is_threadlocal and !dg.mod.single_threaded) try fwd.writeAll("zig_threadlocal "); try dg.renderTypeAndName( fwd, @@ -2994,10 +3005,10 @@ pub fn genDecl(o: *Object) !void { switch (ip.indexToKey(nav.status.fully_resolved.val)) { .@"extern" => |@"extern"| { if (!ip.isFunctionType(nav_ty.toIntern())) return o.dg.renderFwdDecl(o.dg.pass.nav, .{ - .is_extern = true, .is_const = @"extern".is_const, .is_threadlocal = @"extern".is_threadlocal, - .is_weak_linkage = @"extern".is_weak_linkage, + .linkage = @"extern".linkage, + .visibility = @"extern".visibility, }); const fwd = o.dg.fwdDeclWriter(); @@ -3016,13 +3027,12 @@ pub fn genDecl(o: *Object) !void { }, .variable => |variable| { try o.dg.renderFwdDecl(o.dg.pass.nav, .{ - .is_extern = false, .is_const = false, .is_threadlocal = variable.is_threadlocal, - .is_weak_linkage = variable.is_weak_linkage, + .linkage = .internal, + .visibility = .default, }); const w = o.writer(); - if (variable.is_weak_linkage) try w.writeAll("zig_weak_linkage "); if (variable.is_threadlocal and !o.dg.mod.single_threaded) try w.writeAll("zig_threadlocal "); if (nav.status.fully_resolved.@"linksection".toSlice(&zcu.intern_pool)) |s| try w.print("zig_linksection({s}) ", .{fmtStringLiteral(s, null)}); @@ -3467,7 +3477,7 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, .error_set_has_value => return f.fail("TODO: C backend: implement error_set_has_value", .{}), .vector_store_elem => return f.fail("TODO: C backend: implement vector_store_elem", .{}), - .tlv_dllimport_ptr => try airTlvDllimportPtr(f, inst), + .runtime_nav_ptr => try airRuntimeNavPtr(f, inst), .c_va_start => try airCVaStart(f, inst), .c_va_arg => try airCVaArg(f, inst), @@ -7672,7 +7682,7 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue { return local; } -fn airTlvDllimportPtr(f: *Function, inst: Air.Inst.Index) !CValue { +fn airRuntimeNavPtr(f: *Function, inst: Air.Inst.Index) !CValue { const ty_nav = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_nav; const writer = f.object.writer(); const local = try f.allocLocal(inst, .fromInterned(ty_nav.ty)); diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 7790840d20..3fc6250d3f 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -2979,36 +2979,49 @@ pub const Object = struct { const zcu = pt.zcu; const ip = &zcu.intern_pool; const nav = ip.getNav(nav_index); - const is_extern, const is_threadlocal, const is_weak_linkage, const is_dll_import = switch (nav.status) { + const linkage: std.builtin.GlobalLinkage, const visibility: Builder.Visibility, const is_threadlocal, const is_dll_import = switch (nav.status) { .unresolved => unreachable, .fully_resolved => |r| switch (ip.indexToKey(r.val)) { - .variable => |variable| .{ false, variable.is_threadlocal, variable.is_weak_linkage, false }, - .@"extern" => |@"extern"| .{ true, @"extern".is_threadlocal, @"extern".is_weak_linkage, @"extern".is_dll_import }, - else => .{ false, false, false, false }, + .variable => |variable| .{ .internal, .default, variable.is_threadlocal, false }, + .@"extern" => |@"extern"| .{ @"extern".linkage, .fromSymbolVisibility(@"extern".visibility), @"extern".is_threadlocal, @"extern".is_dll_import }, + else => .{ .internal, .default, false, false }, }, // This means it's a source declaration which is not `extern`! - .type_resolved => |r| .{ false, r.is_threadlocal, false, false }, + .type_resolved => |r| .{ .internal, .default, r.is_threadlocal, false }, }; const variable_index = try o.builder.addVariable( - try o.builder.strtabString((if (is_extern) nav.name else nav.fqn).toSlice(ip)), + try o.builder.strtabString(switch (linkage) { + .internal => nav.fqn, + .strong, .weak => nav.name, + .link_once => unreachable, + }.toSlice(ip)), try o.lowerType(Type.fromInterned(nav.typeOf(ip))), toLlvmGlobalAddressSpace(nav.getAddrspace(), zcu.getTarget()), ); gop.value_ptr.* = variable_index.ptrConst(&o.builder).global; // This is needed for declarations created by `@extern`. - if (is_extern) { - variable_index.setLinkage(.external, &o.builder); - variable_index.setUnnamedAddr(.default, &o.builder); - if (is_threadlocal and !zcu.navFileScope(nav_index).mod.?.single_threaded) - variable_index.setThreadLocal(.generaldynamic, &o.builder); - if (is_weak_linkage) variable_index.setLinkage(.extern_weak, &o.builder); - if (is_dll_import) variable_index.setDllStorageClass(.dllimport, &o.builder); - } else { - variable_index.setLinkage(.internal, &o.builder); - variable_index.setUnnamedAddr(.unnamed_addr, &o.builder); - } + switch (linkage) { + .internal => { + variable_index.setLinkage(.internal, &o.builder); + variable_index.setUnnamedAddr(.unnamed_addr, &o.builder); + }, + .strong, .weak => { + variable_index.setLinkage(switch (linkage) { + .internal => unreachable, + .strong => .external, + .weak => .extern_weak, + .link_once => unreachable, + }, &o.builder); + variable_index.setUnnamedAddr(.default, &o.builder); + if (is_threadlocal and !zcu.navFileScope(nav_index).mod.?.single_threaded) + variable_index.setThreadLocal(.generaldynamic, &o.builder); + if (is_dll_import) variable_index.setDllStorageClass(.dllimport, &o.builder); + }, + .link_once => unreachable, + } + variable_index.setVisibility(visibility, &o.builder); return variable_index; } @@ -4530,14 +4543,14 @@ pub const NavGen = struct { const nav = ip.getNav(nav_index); const resolved = nav.status.fully_resolved; - const is_extern, const lib_name, const is_threadlocal, const is_weak_linkage, const is_dll_import, const is_const, const init_val, const owner_nav = switch (ip.indexToKey(resolved.val)) { - .variable => |variable| .{ false, .none, variable.is_threadlocal, variable.is_weak_linkage, false, false, variable.init, variable.owner_nav }, - .@"extern" => |@"extern"| .{ true, @"extern".lib_name, @"extern".is_threadlocal, @"extern".is_weak_linkage, @"extern".is_dll_import, @"extern".is_const, .none, @"extern".owner_nav }, - else => .{ false, .none, false, false, false, true, resolved.val, nav_index }, + const lib_name, const linkage, const visibility: Builder.Visibility, const is_threadlocal, const is_dll_import, const is_const, const init_val, const owner_nav = switch (ip.indexToKey(resolved.val)) { + .variable => |variable| .{ .none, .internal, .default, variable.is_threadlocal, false, false, variable.init, variable.owner_nav }, + .@"extern" => |@"extern"| .{ @"extern".lib_name, @"extern".linkage, .fromSymbolVisibility(@"extern".visibility), @"extern".is_threadlocal, @"extern".is_dll_import, @"extern".is_const, .none, @"extern".owner_nav }, + else => .{ .none, .internal, .default, false, false, true, resolved.val, nav_index }, }; const ty = Type.fromInterned(nav.typeOf(ip)); - if (is_extern and ip.isFunctionType(ty.toIntern())) { + if (linkage != .internal and ip.isFunctionType(ty.toIntern())) { _ = try o.resolveLlvmFunction(owner_nav); } else { const variable_index = try o.resolveGlobalNav(nav_index); @@ -4549,6 +4562,7 @@ pub const NavGen = struct { .none => .no_init, else => try o.lowerValue(init_val), }, &o.builder); + variable_index.setVisibility(visibility, &o.builder); const file_scope = zcu.navFileScopeIndex(nav_index); const mod = zcu.fileByIndex(file_scope).mod.?; @@ -4568,7 +4582,7 @@ pub const NavGen = struct { line_number, try o.lowerDebugType(ty), variable_index, - .{ .local = !is_extern }, + .{ .local = linkage == .internal }, ); const debug_expression = try o.builder.debugExpression(&.{}); @@ -4583,38 +4597,47 @@ pub const NavGen = struct { } } - if (is_extern) { - const global_index = o.nav_map.get(nav_index).?; + switch (linkage) { + .internal => {}, + .strong, .weak => { + const global_index = o.nav_map.get(nav_index).?; - const decl_name = decl_name: { - if (zcu.getTarget().cpu.arch.isWasm() and ty.zigTypeTag(zcu) == .@"fn") { - if (lib_name.toSlice(ip)) |lib_name_slice| { - if (!std.mem.eql(u8, lib_name_slice, "c")) { - break :decl_name try o.builder.strtabStringFmt("{}|{s}", .{ nav.name.fmt(ip), lib_name_slice }); + const decl_name = decl_name: { + if (zcu.getTarget().cpu.arch.isWasm() and ty.zigTypeTag(zcu) == .@"fn") { + if (lib_name.toSlice(ip)) |lib_name_slice| { + if (!std.mem.eql(u8, lib_name_slice, "c")) { + break :decl_name try o.builder.strtabStringFmt("{}|{s}", .{ nav.name.fmt(ip), lib_name_slice }); + } } } - } - break :decl_name try o.builder.strtabString(nav.name.toSlice(ip)); - }; + break :decl_name try o.builder.strtabString(nav.name.toSlice(ip)); + }; - if (o.builder.getGlobal(decl_name)) |other_global| { - if (other_global != global_index) { - // Another global already has this name; just use it in place of this global. - try global_index.replace(other_global, &o.builder); - return; + if (o.builder.getGlobal(decl_name)) |other_global| { + if (other_global != global_index) { + // Another global already has this name; just use it in place of this global. + try global_index.replace(other_global, &o.builder); + return; + } } - } - try global_index.rename(decl_name, &o.builder); - global_index.setLinkage(.external, &o.builder); - global_index.setUnnamedAddr(.default, &o.builder); - if (is_dll_import) { - global_index.setDllStorageClass(.dllimport, &o.builder); - } else if (zcu.comp.config.dll_export_fns) { - global_index.setDllStorageClass(.default, &o.builder); - } + try global_index.rename(decl_name, &o.builder); + global_index.setUnnamedAddr(.default, &o.builder); + if (is_dll_import) { + global_index.setDllStorageClass(.dllimport, &o.builder); + } else if (zcu.comp.config.dll_export_fns) { + global_index.setDllStorageClass(.default, &o.builder); + } - if (is_weak_linkage) global_index.setLinkage(.extern_weak, &o.builder); + global_index.setLinkage(switch (linkage) { + .internal => unreachable, + .strong => .external, + .weak => .extern_weak, + .link_once => unreachable, + }, &o.builder); + global_index.setVisibility(visibility, &o.builder); + }, + .link_once => unreachable, } } }; @@ -5023,7 +5046,7 @@ pub const FuncGen = struct { .vector_store_elem => try self.airVectorStoreElem(inst), - .tlv_dllimport_ptr => try self.airTlvDllimportPtr(inst), + .runtime_nav_ptr => try self.airRuntimeNavPtr(inst), .inferred_alloc, .inferred_alloc_comptime => unreachable, @@ -8122,7 +8145,7 @@ pub const FuncGen = struct { return .none; } - fn airTlvDllimportPtr(fg: *FuncGen, inst: Air.Inst.Index) !Builder.Value { + fn airRuntimeNavPtr(fg: *FuncGen, inst: Air.Inst.Index) !Builder.Value { const o = fg.ng.object; const ty_nav = fg.air.instructions.items(.data)[@intFromEnum(inst)].ty_nav; const llvm_ptr_const = try o.lowerNavRefValue(ty_nav.nav); |
