authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-02-05 13:54:56-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-02-06 14:23:23-08:00
logd20d934a8a096607efda7e956a2131726036b09e
treeddc95eac3111e43f0706e392da756c76086f88dc
parentdef36f2e4460ec9dd500772daac100a655f019b7

std: fix compilation under -lc


3 files changed, 70 insertions(+), 41 deletions(-)

lib/std/c.zig+6
...@@ -7867,6 +7867,11 @@ pub const MAP = switch (native_os) {...@@ -7867,6 +7867,11 @@ pub const MAP = switch (native_os) {
7867 else => void,7867 else => void,
7868};7868};
78697869
7870pub const MREMAP = switch (native_os) {
7871 .linux => linux.MREMAP,
7872 else => void,
7873};
7874
7870/// Used by libc to communicate failure. Not actually part of the underlying syscall.7875/// Used by libc to communicate failure. Not actually part of the underlying syscall.
7871pub const MAP_FAILED: *anyopaque = @ptrFromInt(maxInt(usize));7876pub const MAP_FAILED: *anyopaque = @ptrFromInt(maxInt(usize));
78727877
...@@ -9508,6 +9513,7 @@ pub extern "c" fn write(fd: fd_t, buf: [*]const u8, nbyte: usize) isize;...@@ -9508,6 +9513,7 @@ pub extern "c" fn write(fd: fd_t, buf: [*]const u8, nbyte: usize) isize;
9508pub extern "c" fn pwrite(fd: fd_t, buf: [*]const u8, nbyte: usize, offset: off_t) isize;9513pub extern "c" fn pwrite(fd: fd_t, buf: [*]const u8, nbyte: usize, offset: off_t) isize;
9509pub extern "c" fn mmap(addr: ?*align(page_size) anyopaque, len: usize, prot: c_uint, flags: MAP, fd: fd_t, offset: off_t) *anyopaque;9514pub extern "c" fn mmap(addr: ?*align(page_size) anyopaque, len: usize, prot: c_uint, flags: MAP, fd: fd_t, offset: off_t) *anyopaque;
9510pub extern "c" fn munmap(addr: *align(page_size) const anyopaque, len: usize) c_int;9515pub extern "c" fn munmap(addr: *align(page_size) const anyopaque, len: usize) c_int;
9516pub extern "c" fn mremap(addr: ?*align(page_size) const anyopaque, old_len: usize, new_len: usize, flags: MREMAP, ...) *anyopaque;
9511pub extern "c" fn mprotect(addr: *align(page_size) anyopaque, len: usize, prot: c_uint) c_int;9517pub extern "c" fn mprotect(addr: *align(page_size) anyopaque, len: usize, prot: c_uint) c_int;
9512pub extern "c" fn link(oldpath: [*:0]const u8, newpath: [*:0]const u8) c_int;9518pub extern "c" fn link(oldpath: [*:0]const u8, newpath: [*:0]const u8) c_int;
9513pub extern "c" fn linkat(oldfd: fd_t, oldpath: [*:0]const u8, newfd: fd_t, newpath: [*:0]const u8, flags: c_int) c_int;9519pub extern "c" fn linkat(oldfd: fd_t, oldpath: [*:0]const u8, newfd: fd_t, newpath: [*:0]const u8, flags: c_int) c_int;
lib/std/heap.zig+63-39
...@@ -124,6 +124,13 @@ const CAllocator = struct {...@@ -124,6 +124,13 @@ const CAllocator = struct {
124 }124 }
125 }125 }
126126
127 const vtable: Allocator.VTable = .{
128 .alloc = alloc,
129 .resize = resize,
130 .remap = remap,
131 .free = free,
132 };
133
127 pub const supports_malloc_size = @TypeOf(malloc_size) != void;134 pub const supports_malloc_size = @TypeOf(malloc_size) != void;
128 pub const malloc_size = if (@TypeOf(c.malloc_size) != void)135 pub const malloc_size = if (@TypeOf(c.malloc_size) != void)
129 c.malloc_size136 c.malloc_size
...@@ -139,7 +146,7 @@ const CAllocator = struct {...@@ -139,7 +146,7 @@ const CAllocator = struct {
139 };146 };
140147
141 fn getHeader(ptr: [*]u8) *[*]u8 {148 fn getHeader(ptr: [*]u8) *[*]u8 {
142 return @as(*[*]u8, @ptrFromInt(@intFromPtr(ptr) - @sizeOf(usize)));149 return @ptrCast(ptr - @sizeOf(usize));
143 }150 }
144151
145 fn alignedAlloc(len: usize, alignment: mem.Alignment) ?[*]u8 {152 fn alignedAlloc(len: usize, alignment: mem.Alignment) ?[*]u8 {
...@@ -147,13 +154,13 @@ const CAllocator = struct {...@@ -147,13 +154,13 @@ const CAllocator = struct {
147 if (supports_posix_memalign) {154 if (supports_posix_memalign) {
148 // The posix_memalign only accepts alignment values that are a155 // The posix_memalign only accepts alignment values that are a
149 // multiple of the pointer size156 // multiple of the pointer size
150 const eff_alignment = @max(alignment_bytes, @sizeOf(usize));157 const effective_alignment = @max(alignment_bytes, @sizeOf(usize));
151158
152 var aligned_ptr: ?*anyopaque = undefined;159 var aligned_ptr: ?*anyopaque = undefined;
153 if (c.posix_memalign(&aligned_ptr, eff_alignment, len) != 0)160 if (c.posix_memalign(&aligned_ptr, effective_alignment, len) != 0)
154 return null;161 return null;
155162
156 return @as([*]u8, @ptrCast(aligned_ptr));163 return @ptrCast(aligned_ptr);
157 }164 }
158165
159 // Thin wrapper around regular malloc, overallocate to account for166 // Thin wrapper around regular malloc, overallocate to account for
...@@ -219,6 +226,18 @@ const CAllocator = struct {...@@ -219,6 +226,18 @@ const CAllocator = struct {
219 return false;226 return false;
220 }227 }
221228
229 fn remap(
230 context: *anyopaque,
231 memory: []u8,
232 alignment: mem.Alignment,
233 new_len: usize,
234 return_address: usize,
235 ) ?[*]u8 {
236 // realloc would potentially return a new allocation that does not
237 // respect the original alignment.
238 return if (resize(context, memory, alignment, new_len, return_address)) memory.ptr else null;
239 }
240
222 fn free(241 fn free(
223 _: *anyopaque,242 _: *anyopaque,
224 buf: []u8,243 buf: []u8,
...@@ -234,39 +253,36 @@ const CAllocator = struct {...@@ -234,39 +253,36 @@ const CAllocator = struct {
234/// Supports the full Allocator interface, including alignment, and exploiting253/// Supports the full Allocator interface, including alignment, and exploiting
235/// `malloc_usable_size` if available. For an allocator that directly calls254/// `malloc_usable_size` if available. For an allocator that directly calls
236/// `malloc`/`free`, see `raw_c_allocator`.255/// `malloc`/`free`, see `raw_c_allocator`.
237pub const c_allocator = Allocator{256pub const c_allocator: Allocator = .{
238 .ptr = undefined,257 .ptr = undefined,
239 .vtable = &c_allocator_vtable,258 .vtable = &CAllocator.vtable,
240};
241const c_allocator_vtable = Allocator.VTable{
242 .alloc = CAllocator.alloc,
243 .resize = CAllocator.resize,
244 .free = CAllocator.free,
245};259};
246260
247/// Asserts allocations are within `@alignOf(std.c.max_align_t)` and directly calls261/// Asserts allocations are within `@alignOf(std.c.max_align_t)` and directly
248/// `malloc`/`free`. Does not attempt to utilize `malloc_usable_size`.262/// calls `malloc`/`free`. Does not attempt to utilize `malloc_usable_size`.
249/// This allocator is safe to use as the backing allocator with263/// This allocator is safe to use as the backing allocator with
250/// `ArenaAllocator` for example and is more optimal in such a case264/// `ArenaAllocator` for example and is more optimal in such a case than
251/// than `c_allocator`.265/// `c_allocator`.
252pub const raw_c_allocator = Allocator{266pub const raw_c_allocator: Allocator = .{
253 .ptr = undefined,267 .ptr = undefined,
254 .vtable = &raw_c_allocator_vtable,268 .vtable = &raw_c_allocator_vtable,
255};269};
256const raw_c_allocator_vtable = Allocator.VTable{270const raw_c_allocator_vtable: Allocator.VTable = .{
257 .alloc = rawCAlloc,271 .alloc = rawCAlloc,
258 .resize = rawCResize,272 .resize = rawCResize,
273 .remap = rawCRemap,
259 .free = rawCFree,274 .free = rawCFree,
260};275};
261276
262fn rawCAlloc(277fn rawCAlloc(
263 _: *anyopaque,278 context: *anyopaque,
264 len: usize,279 len: usize,
265 alignment: mem.Alignment,280 alignment: mem.Alignment,
266 ret_addr: usize,281 return_address: usize,
267) ?[*]u8 {282) ?[*]u8 {
268 _ = ret_addr;283 _ = context;
269 assert(alignment.order(.le, comptime .fromByteUnits(@alignOf(std.c.max_align_t))));284 _ = return_address;
285 assert(alignment.compare(.lte, comptime .fromByteUnits(@alignOf(std.c.max_align_t))));
270 // Note that this pointer cannot be aligncasted to max_align_t because if286 // Note that this pointer cannot be aligncasted to max_align_t because if
271 // len is < max_align_t then the alignment can be smaller. For example, if287 // len is < max_align_t then the alignment can be smaller. For example, if
272 // max_align_t is 16, but the user requests 8 bytes, there is no built-in288 // max_align_t is 16, but the user requests 8 bytes, there is no built-in
...@@ -277,35 +293,43 @@ fn rawCAlloc(...@@ -277,35 +293,43 @@ fn rawCAlloc(
277}293}
278294
279fn rawCResize(295fn rawCResize(
280 _: *anyopaque,296 context: *anyopaque,
281 buf: []u8,297 memory: []u8,
282 alignment: mem.Alignment,298 alignment: mem.Alignment,
283 new_len: usize,299 new_len: usize,
284 ret_addr: usize,300 return_address: usize,
285) bool {301) bool {
302 _ = context;
303 _ = memory;
286 _ = alignment;304 _ = alignment;
287 _ = ret_addr;305 _ = new_len;
288306 _ = return_address;
289 if (new_len <= buf.len)
290 return true;
291
292 if (CAllocator.supports_malloc_size) {
293 const full_len = CAllocator.malloc_size(buf.ptr);
294 if (new_len <= full_len) return true;
295 }
296
297 return false;307 return false;
298}308}
299309
310fn rawCRemap(
311 context: *anyopaque,
312 memory: []u8,
313 alignment: mem.Alignment,
314 new_len: usize,
315 return_address: usize,
316) ?[*]u8 {
317 _ = context;
318 _ = alignment;
319 _ = return_address;
320 return @ptrCast(c.realloc(memory.ptr, new_len));
321}
322
300fn rawCFree(323fn rawCFree(
301 _: *anyopaque,324 context: *anyopaque,
302 buf: []u8,325 memory: []u8,
303 alignment: mem.Alignment,326 alignment: mem.Alignment,
304 ret_addr: usize,327 return_address: usize,
305) void {328) void {
329 _ = context;
306 _ = alignment;330 _ = alignment;
307 _ = ret_addr;331 _ = return_address;
308 c.free(buf.ptr);332 c.free(memory.ptr);
309}333}
310334
311/// On operating systems that support memory mapping, this allocator makes a335/// On operating systems that support memory mapping, this allocator makes a
lib/std/heap/PageAllocator.zig+1-2
...@@ -172,8 +172,7 @@ fn realloc(uncasted_memory: []u8, new_len: usize, may_move: bool) ?[*]u8 {...@@ -172,8 +172,7 @@ fn realloc(uncasted_memory: []u8, new_len: usize, may_move: bool) ?[*]u8 {
172 if (new_size_aligned == page_aligned_len)172 if (new_size_aligned == page_aligned_len)
173 return memory.ptr;173 return memory.ptr;
174174
175 const mremap_available = native_os == .linux;175 if (posix.MREMAP != void) {
176 if (mremap_available) {
177 // TODO: if the next_mmap_addr_hint is within the remapped range, update it176 // TODO: if the next_mmap_addr_hint is within the remapped range, update it
178 const new_memory = posix.mremap(memory.ptr, memory.len, new_len, .{ .MAYMOVE = may_move }, null) catch return null;177 const new_memory = posix.mremap(memory.ptr, memory.len, new_len, .{ .MAYMOVE = may_move }, null) catch return null;
179 return new_memory.ptr;178 return new_memory.ptr;