zig/lib/std/special/c.zig
Andrew Kelley 63cbec1a96 stage2: add more functions to freestanding libc
The log functions are not passing behavior tests.
2022-02-17 13:11:58 -07:00

181 lines
4.6 KiB
Zig

//! 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 math = std.math;
const native_os = builtin.os.tag;
const long_double_is_f128 = builtin.target.longDoubleIsF128();
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_backend == .stage1) {
_ = @import("c_stage1.zig");
}
@export(memset, .{ .name = "memset", .linkage = .Strong });
@export(__memset, .{ .name = "__memset", .linkage = .Strong });
@export(memcpy, .{ .name = "memcpy", .linkage = .Strong });
@export(trunc, .{ .name = "trunc", .linkage = .Strong });
@export(truncf, .{ .name = "truncf", .linkage = .Strong });
@export(truncl, .{ .name = "truncl", .linkage = .Strong });
@export(log, .{ .name = "log", .linkage = .Strong });
@export(logf, .{ .name = "logf", .linkage = .Strong });
@export(sin, .{ .name = "sin", .linkage = .Strong });
@export(sinf, .{ .name = "sinf", .linkage = .Strong });
@export(cos, .{ .name = "cos", .linkage = .Strong });
@export(cosf, .{ .name = "cosf", .linkage = .Strong });
@export(exp, .{ .name = "exp", .linkage = .Strong });
@export(expf, .{ .name = "expf", .linkage = .Strong });
@export(exp2, .{ .name = "exp2", .linkage = .Strong });
@export(exp2f, .{ .name = "exp2f", .linkage = .Strong });
@export(log2, .{ .name = "log2", .linkage = .Strong });
@export(log2f, .{ .name = "log2f", .linkage = .Strong });
@export(log10, .{ .name = "log10", .linkage = .Strong });
@export(log10f, .{ .name = "log10f", .linkage = .Strong });
}
// 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_backend != .stage1) {
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 __memset(dest: ?[*]u8, c: u8, n: usize, dest_n: usize) callconv(.C) ?[*]u8 {
if (dest_n < n)
@panic("buffer overflow");
return memset(dest, c, n);
}
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[0] = s[0];
n -= 1;
if (n == 0) break;
d += 1;
s += 1;
}
}
return dest;
}
fn trunc(a: f64) callconv(.C) f64 {
return math.trunc(a);
}
fn truncf(a: f32) callconv(.C) f32 {
return math.trunc(a);
}
fn truncl(a: c_longdouble) callconv(.C) c_longdouble {
if (!long_double_is_f128) {
@panic("TODO implement this");
}
return math.trunc(a);
}
fn log(a: f64) callconv(.C) f64 {
return math.ln(a);
}
fn logf(a: f32) callconv(.C) f32 {
return math.ln(a);
}
fn sin(a: f64) callconv(.C) f64 {
return math.sin(a);
}
fn sinf(a: f32) callconv(.C) f32 {
return math.sin(a);
}
fn cos(a: f64) callconv(.C) f64 {
return math.cos(a);
}
fn cosf(a: f32) callconv(.C) f32 {
return math.cos(a);
}
fn exp(a: f64) callconv(.C) f64 {
return math.exp(a);
}
fn expf(a: f32) callconv(.C) f32 {
return math.exp(a);
}
fn exp2(a: f64) callconv(.C) f64 {
return math.exp2(a);
}
fn exp2f(a: f32) callconv(.C) f32 {
return math.exp2(a);
}
fn log2(a: f64) callconv(.C) f64 {
return math.log2(a);
}
fn log2f(a: f32) callconv(.C) f32 {
return math.log2(a);
}
fn log10(a: f64) callconv(.C) f64 {
return math.log10(a);
}
fn log10f(a: f32) callconv(.C) f32 {
return math.log10(a);
}