aboutsummaryrefslogtreecommitdiff
path: root/lib/std/special/c.zig
blob: a7821643da8890bc5d68ec29dcba3a78b4a7f681 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
//! This is Zig's multi-target implementation of libc.
//! When builtin.link_libc is true, we need to export all the functions and
//! provide an entire C API.
//! Otherwise, only the functions which LLVM generates calls to need to be generated,
//! such as memcpy, memset, and some math functions.

const std = @import("std");
const builtin = @import("builtin");
const native_os = builtin.os.tag;

comptime {
    // When the self-hosted compiler is further along, all the logic from c_stage1.zig will
    // be migrated to this file and then c_stage1.zig will be deleted. Until then we have a
    // simpler implementation of c.zig that only uses features already implemented in self-hosted.
    if (builtin.zig_is_stage2) {
        @export(memset, .{ .name = "memset", .linkage = .Strong });
        @export(memcpy, .{ .name = "memcpy", .linkage = .Strong });
    } else {
        _ = @import("c_stage1.zig");
    }
}

// Avoid dragging in the runtime safety mechanisms into this .o file,
// unless we're trying to test this file.
pub fn panic(msg: []const u8, error_return_trace: ?*std.builtin.StackTrace) noreturn {
    @setCold(true);
    _ = error_return_trace;
    if (builtin.zig_is_stage2) {
        while (true) {
            @breakpoint();
        }
    }
    if (builtin.is_test) {
        std.debug.panic("{s}", .{msg});
    }
    if (native_os != .freestanding and native_os != .other) {
        std.os.abort();
    }
    while (true) {}
}

fn memset(dest: ?[*]u8, c: u8, len: usize) callconv(.C) ?[*]u8 {
    @setRuntimeSafety(false);

    if (len != 0) {
        var d = dest.?;
        var n = len;
        while (true) {
            d.* = c;
            n -= 1;
            if (n == 0) break;
            d += 1;
        }
    }

    return dest;
}

fn memcpy(noalias dest: ?[*]u8, noalias src: ?[*]const u8, len: usize) callconv(.C) ?[*]u8 {
    @setRuntimeSafety(false);

    if (len != 0) {
        var d = dest.?;
        var s = src.?;
        var n = len;
        while (true) {
            d.* = s.*;
            n -= 1;
            if (n == 0) break;
            d += 1;
            s += 1;
        }
    }

    return dest;
}