1//! This is Zig's multi-target implementation of libc.
2//! When builtin.link_libc is true, we need to export all the functions and
3//! provide an entire C API.
4//! Otherwise, only the functions which LLVM generates calls to need to be generated,
5//! such as memcpy, memset, and some math functions.
6
7const std = @import("std");
8const builtin = @import("builtin");
9const native_os = builtin.os.tag;
10
11comptime {
12    // When the self-hosted compiler is further along, all the logic from c_stage1.zig will
13    // be migrated to this file and then c_stage1.zig will be deleted. Until then we have a
14    // simpler implementation of c.zig that only uses features already implemented in self-hosted.
15    if (builtin.zig_is_stage2) {
16        @export(memset, .{ .name = "memset", .linkage = .Strong });
17        @export(memcpy, .{ .name = "memcpy", .linkage = .Strong });
18    } else {
19        _ = @import("c_stage1.zig");
20    }
21}
22
23// Avoid dragging in the runtime safety mechanisms into this .o file,
24// unless we're trying to test this file.
25pub fn panic(msg: []const u8, error_return_trace: ?*std.builtin.StackTrace) noreturn {
26    @setCold(true);
27    _ = error_return_trace;
28    if (builtin.zig_is_stage2) {
29        while (true) {
30            @breakpoint();
31        }
32    }
33    if (builtin.is_test) {
34        std.debug.panic("{s}", .{msg});
35    }
36    if (native_os != .freestanding and native_os != .other) {
37        std.os.abort();
38    }
39    while (true) {}
40}
41
42fn memset(dest: ?[*]u8, c: u8, len: usize) callconv(.C) ?[*]u8 {
43    @setRuntimeSafety(false);
44
45    if (len != 0) {
46        var d = dest.?;
47        var n = len;
48        while (true) {
49            d.* = c;
50            n -= 1;
51            if (n == 0) break;
52            d += 1;
53        }
54    }
55
56    return dest;
57}
58
59fn memcpy(noalias dest: ?[*]u8, noalias src: ?[*]const u8, len: usize) callconv(.C) ?[*]u8 {
60    @setRuntimeSafety(false);
61
62    if (len != 0) {
63        var d = dest.?;
64        var s = src.?;
65        var n = len;
66        while (true) {
67            d.* = s.*;
68            n -= 1;
69            if (n == 0) break;
70            d += 1;
71            s += 1;
72        }
73    }
74
75    return dest;
76}
77