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