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) {
78677867 else => void,
78687868};
78697869
7870pub const MREMAP = switch (native_os) {
7871 .linux => linux.MREMAP,
7872 else => void,
7873};
7874
78707875/// Used by libc to communicate failure. Not actually part of the underlying syscall.
78717876pub 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;
95089513pub extern "c" fn pwrite(fd: fd_t, buf: [*]const u8, nbyte: usize, offset: off_t) isize;
95099514pub extern "c" fn mmap(addr: ?*align(page_size) anyopaque, len: usize, prot: c_uint, flags: MAP, fd: fd_t, offset: off_t) *anyopaque;
95109515pub 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;
95119517pub extern "c" fn mprotect(addr: *align(page_size) anyopaque, len: usize, prot: c_uint) c_int;
95129518pub extern "c" fn link(oldpath: [*:0]const u8, newpath: [*:0]const u8) c_int;
95139519pub 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 {
124124 }
125125 }
126126
127 const vtable: Allocator.VTable = .{
128 .alloc = alloc,
129 .resize = resize,
130 .remap = remap,
131 .free = free,
132 };
133
127134 pub const supports_malloc_size = @TypeOf(malloc_size) != void;
128135 pub const malloc_size = if (@TypeOf(c.malloc_size) != void)
129136 c.malloc_size
......@@ -139,7 +146,7 @@ const CAllocator = struct {
139146 };
140147
141148 fn getHeader(ptr: [*]u8) *[*]u8 {
142 return @as(*[*]u8, @ptrFromInt(@intFromPtr(ptr) - @sizeOf(usize)));
149 return @ptrCast(ptr - @sizeOf(usize));
143150 }
144151
145152 fn alignedAlloc(len: usize, alignment: mem.Alignment) ?[*]u8 {
......@@ -147,13 +154,13 @@ const CAllocator = struct {
147154 if (supports_posix_memalign) {
148155 // The posix_memalign only accepts alignment values that are a
149156 // multiple of the pointer size
150 const eff_alignment = @max(alignment_bytes, @sizeOf(usize));
157 const effective_alignment = @max(alignment_bytes, @sizeOf(usize));
151158
152159 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)
154161 return null;
155162
156 return @as([*]u8, @ptrCast(aligned_ptr));
163 return @ptrCast(aligned_ptr);
157164 }
158165
159166 // Thin wrapper around regular malloc, overallocate to account for
......@@ -219,6 +226,18 @@ const CAllocator = struct {
219226 return false;
220227 }
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
222241 fn free(
223242 _: *anyopaque,
224243 buf: []u8,
......@@ -234,39 +253,36 @@ const CAllocator = struct {
234253/// Supports the full Allocator interface, including alignment, and exploiting
235254/// `malloc_usable_size` if available. For an allocator that directly calls
236255/// `malloc`/`free`, see `raw_c_allocator`.
237pub const c_allocator = Allocator{
256pub const c_allocator: Allocator = .{
238257 .ptr = undefined,
239 .vtable = &c_allocator_vtable,
240};
241const c_allocator_vtable = Allocator.VTable{
242 .alloc = CAllocator.alloc,
243 .resize = CAllocator.resize,
244 .free = CAllocator.free,
258 .vtable = &CAllocator.vtable,
245259};
246260
247/// Asserts allocations are within `@alignOf(std.c.max_align_t)` and directly calls
248/// `malloc`/`free`. Does not attempt to utilize `malloc_usable_size`.
261/// Asserts allocations are within `@alignOf(std.c.max_align_t)` and directly
262/// calls `malloc`/`free`. Does not attempt to utilize `malloc_usable_size`.
249263/// This allocator is safe to use as the backing allocator with
250/// `ArenaAllocator` for example and is more optimal in such a case
251/// than `c_allocator`.
252pub const raw_c_allocator = Allocator{
264/// `ArenaAllocator` for example and is more optimal in such a case than
265/// `c_allocator`.
266pub const raw_c_allocator: Allocator = .{
253267 .ptr = undefined,
254268 .vtable = &raw_c_allocator_vtable,
255269};
256const raw_c_allocator_vtable = Allocator.VTable{
270const raw_c_allocator_vtable: Allocator.VTable = .{
257271 .alloc = rawCAlloc,
258272 .resize = rawCResize,
273 .remap = rawCRemap,
259274 .free = rawCFree,
260275};
261276
262277fn rawCAlloc(
263 _: *anyopaque,
278 context: *anyopaque,
264279 len: usize,
265280 alignment: mem.Alignment,
266 ret_addr: usize,
281 return_address: usize,
267282) ?[*]u8 {
268 _ = ret_addr;
269 assert(alignment.order(.le, comptime .fromByteUnits(@alignOf(std.c.max_align_t))));
283 _ = context;
284 _ = return_address;
285 assert(alignment.compare(.lte, comptime .fromByteUnits(@alignOf(std.c.max_align_t))));
270286 // Note that this pointer cannot be aligncasted to max_align_t because if
271287 // len is < max_align_t then the alignment can be smaller. For example, if
272288 // max_align_t is 16, but the user requests 8 bytes, there is no built-in
......@@ -277,35 +293,43 @@ fn rawCAlloc(
277293}
278294
279295fn rawCResize(
280 _: *anyopaque,
281 buf: []u8,
296 context: *anyopaque,
297 memory: []u8,
282298 alignment: mem.Alignment,
283299 new_len: usize,
284 ret_addr: usize,
300 return_address: usize,
285301) bool {
302 _ = context;
303 _ = memory;
286304 _ = alignment;
287 _ = ret_addr;
288
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
305 _ = new_len;
306 _ = return_address;
297307 return false;
298308}
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
300323fn rawCFree(
301 _: *anyopaque,
302 buf: []u8,
324 context: *anyopaque,
325 memory: []u8,
303326 alignment: mem.Alignment,
304 ret_addr: usize,
327 return_address: usize,
305328) void {
329 _ = context;
306330 _ = alignment;
307 _ = ret_addr;
308 c.free(buf.ptr);
331 _ = return_address;
332 c.free(memory.ptr);
309333}
310334
311335/// 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 {
172172 if (new_size_aligned == page_aligned_len)
173173 return memory.ptr;
174174
175 const mremap_available = native_os == .linux;
176 if (mremap_available) {
175 if (posix.MREMAP != void) {
177176 // TODO: if the next_mmap_addr_hint is within the remapped range, update it
178177 const new_memory = posix.mremap(memory.ptr, memory.len, new_len, .{ .MAYMOVE = may_move }, null) catch return null;
179178 return new_memory.ptr;