diff --git a/lib/std/core/env.c3 b/lib/std/core/env.c3 index 05b32da08..fb590310f 100644 --- a/lib/std/core/env.c3 +++ b/lib/std/core/env.c3 @@ -146,6 +146,7 @@ const bool POSIX = LIBC && os_is_posix(); const bool OPENBSD = LIBC && OS_TYPE == OPENBSD; const bool FREEBSD = LIBC && OS_TYPE == FREEBSD; const bool NETBSD = LIBC && OS_TYPE == NETBSD; +const bool BSD_FAMILY = env::FREEBSD || env::OPENBSD || env::NETBSD; const bool WASI = LIBC && OS_TYPE == WASI; const bool WASM_NOLIBC @builtin = !LIBC && ARCH_TYPE == ArchType.WASM32 || ARCH_TYPE == ArchType.WASM64; const bool ADDRESS_SANITIZER = $$ADDRESS_SANITIZER; diff --git a/lib/std/io/os/fileinfo.c3 b/lib/std/io/os/fileinfo.c3 index afde1aab9..360eb0be4 100644 --- a/lib/std/io/os/fileinfo.c3 +++ b/lib/std/io/os/fileinfo.c3 @@ -1,11 +1,11 @@ module std::io::os; import libc, std::os, std::io; -fn void! native_stat(Stat* stat, String path) @if(env::DARWIN || env::LINUX) +fn void! native_stat(Stat* stat, String path) @if(env::DARWIN || env::LINUX || env::BSD_FAMILY) { @pool() { - $if env::DARWIN || env::LINUX: + $if env::DARWIN || env::LINUX || env::BSD_FAMILY: int res = libc::stat(path.zstr_tcopy(), stat); $else unreachable("Stat unimplemented"); @@ -71,6 +71,9 @@ fn bool native_file_or_dir_exists(String path) { $switch $case env::DARWIN: + $case env::FREEBSD: + $case env::NETBSD: + $case env::OPENBSD: $case env::LINUX: Stat stat; return @ok(native_stat(&stat, path)); @@ -93,6 +96,9 @@ fn bool native_is_file(String path) { $switch $case env::DARWIN: + $case env::FREEBSD: + $case env::NETBSD: + $case env::OPENBSD: $case env::LINUX: Stat stat; return @ok(native_stat(&stat, path)) && libc_S_ISTYPE(stat.st_mode, libc::S_IFREG); @@ -105,7 +111,7 @@ fn bool native_is_file(String path) fn bool native_is_dir(String path) { - $if env::DARWIN || env::LINUX: + $if env::DARWIN || env::LINUX || env::BSD_FAMILY: Stat stat; return @ok(native_stat(&stat, path)) && libc_S_ISTYPE(stat.st_mode, libc::S_IFDIR); $else diff --git a/lib/std/libc/libc.c3 b/lib/std/libc/libc.c3 index 7f9803394..cfd380b01 100644 --- a/lib/std/libc/libc.c3 +++ b/lib/std/libc/libc.c3 @@ -3,7 +3,6 @@ // a copy of which can be found in the LICENSE_STDLIB file. module libc; - // Constants need to be per os/arch const int EXIT_FAILURE = 1; const int EXIT_SUCCESS = 0; @@ -203,7 +202,7 @@ macro CFile stdin() => __stdin; macro CFile stdout() => __stdout; macro CFile stderr() => __stderr; -module libc @if(env::DARWIN); +module libc @if(env::DARWIN || env::BSD_FAMILY); extern CFile __stdinp; extern CFile __stdoutp; extern CFile __stderrp; @@ -219,7 +218,7 @@ macro CFile stdin() => __acrt_iob_func(STDIN_FD); macro CFile stdout() => __acrt_iob_func(STDOUT_FD); macro CFile stderr() => __acrt_iob_func(STDERR_FD); -module libc @if(env::LIBC && !env::WIN32 && !env::LINUX && !env::DARWIN); +module libc @if(env::LIBC && !env::WIN32 && !env::LINUX && !env::DARWIN && !env::BSD_FAMILY); macro CFile stdin() { return (CFile*)(uptr)STDIN_FD; } macro CFile stdout() { return (CFile*)(uptr)STDOUT_FD; } macro CFile stderr() { return (CFile*)(uptr)STDERR_FD; } diff --git a/lib/std/libc/os/freebsd.c3 b/lib/std/libc/os/freebsd.c3 new file mode 100644 index 000000000..39b81b24c --- /dev/null +++ b/lib/std/libc/os/freebsd.c3 @@ -0,0 +1,62 @@ +module libc @if(env::FREEBSD); + +// Checked for x86_64, this is notoriously incorrect when comparing with Rust code etc + +def Blksize_t = $typefrom(env::X86_64 ? long.typeid : CInt.typeid); +def Nlink_t = $typefrom(env::X86_64 ? ulong.typeid : CUInt.typeid); +def Blkcnt_t = long; +def Ino_t = ulong; +def Dev_t = ulong; +def Mode_t = uint; +def Ino64_t = ulong; +def Blkcnt64_t = long; + +struct Stat @if(env::X86_64) +{ + Dev_t st_dev; + Ino_t st_ino; + Nlink_t st_nlink; + Mode_t st_mode; + Uid_t st_uid; + Gid_t st_gid; + CInt __pad0; + Dev_t st_rdev; + Off_t st_size; + Blksize_t st_blksize; + Blkcnt_t st_blocks; + Time_t st_atime; + long st_atime_nsec; + Time_t st_mtime; + long st_mtime_nsec; + Time_t st_ctime; + long st_ctime_nsec; + long[3] __unused; +} + +struct Stat @if(!env::X86_64) +{ + Dev_t st_dev; + Ino_t st_ino; + Mode_t st_mode; + Nlink_t st_nlink; + Uid_t st_uid; + Gid_t st_gid; + Dev_t st_rdev; + CInt __pad1; + Off_t st_size; + Blksize_t st_blksize; + CInt __pad2; + Blkcnt_t st_blocks; + Time_t st_atime; + long st_atime_nsec; + Time_t st_mtime; + long st_mtime_nsec; + Time_t st_ctime; + long st_ctime_nsec; + CInt[2] __unused; +} + +extern fn CInt stat(ZString path, Stat* stat); + +extern fn CInt get_nprocs(); +extern fn CInt get_nprocs_conf(); diff --git a/lib/std/os/posix/files.c3 b/lib/std/os/posix/files.c3 index 1aa5d4b6f..c809a4cda 100644 --- a/lib/std/os/posix/files.c3 +++ b/lib/std/os/posix/files.c3 @@ -7,15 +7,22 @@ distinct DIRPtr = void*; struct Posix_dirent { Ino_t d_fileno; - Off_t d_off; + Off_t d_off @if(!env::NETBSD); ushort d_reclen; - ushort d_namelen @if(env::DARWIN); + ushort d_namelen @if(env::DARWIN || env::NETBSD); char d_type; - char d_namelen @if(env::FREEBSD || env::OPENBSD); - uint d_pad0 @if(env::FREEBSD); + + char d_namelen @if(env::OPENBSD); char[4] d_pad0 @if(env::OPENBSD); + + char d_pad0 @if(env::FREEBSD); + ushort d_namelen @if(env::FREEBSD); + ushort d_pad1 @if(env::FREEBSD); + + char[255+1] name @if(env::FREEBSD || env::OPENBSD); + char[511+1] name @if(env::NETBSD); char[1024] name @if(env::DARWIN); - char[*] name @if(!env::DARWIN); + char[*] name @if(!env::DARWIN && !env::BSD_FAMILY); } extern fn int rmdir(ZString); @@ -41,4 +48,3 @@ const DT_WHT = 14; const USE_DARWIN_INODE64 = env::DARWIN && env::X86_64; extern fn Posix_dirent* readdir(DIRPtr) @extern("readdir$INODE64") @if(USE_DARWIN_INODE64); - diff --git a/resources/examples/nolibc-freebsd/hello_world.c3 b/resources/examples/nolibc-freebsd/hello_world.c3 new file mode 100644 index 000000000..d2b130a9c --- /dev/null +++ b/resources/examples/nolibc-freebsd/hello_world.c3 @@ -0,0 +1,22 @@ +fn int main() +{ + String msg = "Hello, C3 World!\n"; + $$syscall(4, 1, (uptr)msg.ptr, msg.len); // __NR_write, STDOUT + return 0; +} + +fn void _start() @export("_start") +{ + int ret = main(); + $$syscall(1, ret); // __NR_exit +} + +module std::core::builtin; + +def PanicFn = fn void(String message, String file, String function, uint line); + +PanicFn panic = &default_panic; + +fn void default_panic(String message, String file, String function, uint line) +{ +} diff --git a/resources/examples/nolibc-freebsd/project.json b/resources/examples/nolibc-freebsd/project.json new file mode 100644 index 000000000..352dcc66e --- /dev/null +++ b/resources/examples/nolibc-freebsd/project.json @@ -0,0 +1,79 @@ +{ + // Language version of C3. + "langrev": "1", + // Warnings used for all targets. + "warnings": [ "no-unused" ], + // Directories where C3 library files may be found. + "dependency-search-paths": [ ], + // Libraries to use for all targets. + "dependencies": [ ], + // Authors, optionally with email. + "authors": [ "John Doe " ], + // Version using semantic versioning. + "version": "0.1.0", + // Sources compiled for all targets. + "sources": [ "./**" ], + // C sources if the project also compiles C sources + // relative to the project file. + // "c-sources": [ "csource/**" ], + // Output location, relative to project file. + "output": ".", + // Architecture and OS target. + // You can use 'c3c --list-targets' to list all valid targets. + "target": "freebsd-x64", + // Targets. + "targets": { + "hello_world": { + "type": "executable", + "debug-info": "none", + "link-libc": false, + "opt": "O0", + "safe": false, + "linker": "builtin", + "use-stdlib": false, + }, + }, + // Global settings. + // C compiler if the project also compiles C sources + // defaults to 'cc'. + "cc": "cc", + // CPU name, used for optimizations in the LLVM backend. + "cpu": "generic", + // Debug information, may be "none", "full" and "line-tables". + "debug-info": "full", + // FP math behaviour: "strict", "relaxed", "fast". + "fp-math": "strict", + // Link libc other default libraries. + "link-libc": true, + // Memory environment: "normal", "small", "tiny", "none". + "memory-env": "normal", + // Optimization: "O0", "O1", "O2", "O3", "O4", "O5", "Os", "Oz". + "opt": "O0", + // Code optimization level: "none", "less", "more", "max". + "optlevel": "none", + // Code size optimization: "none", "small", "tiny". + "optsize": "none", + // Relocation model: "none", "pic", "PIC", "pie", "PIE". + "reloc": "none", + // Trap on signed and unsigned integer wrapping for testing. + "trap-on-wrap": false, + // Turn safety (contracts, runtime bounds checking, null pointer checks etc). + "safe": true, + // Compile all modules together, enables more inlining. + "single-module": true, + // Use / don't use soft float, value is otherwise target default. + "soft-float": false, + // Strip unused code and globals from the output. + "strip-unused": true, + // The size of the symtab, which limits the amount + // of symbols that can be used. Should usually not be changed. + "symtab": 1048576, + // Select linker. + "linker": "cc", + // Include the standard library. + "use-stdlib": true, + // Set general level of x64 cpu: "baseline", "ssse3", "sse4", "avx1", "avx2-v1", "avx2-v2", "avx512", "native". + "x86cpu": "native", + // Set max type of vector use: "none", "mmx", "sse", "avx", "avx512", "native". + "x86vec": "sse", +} diff --git a/resources/testfragments/demo1.c3 b/resources/testfragments/demo1.c3 index 74e2d2ee2..967160da6 100644 --- a/resources/testfragments/demo1.c3 +++ b/resources/testfragments/demo1.c3 @@ -34,7 +34,7 @@ fn void testStruct() foo = { 11, 12 }; // Named arguments - foo = createFoo(.b = 13, .a = 14); + foo = createFoo(a: 14, b: 13); printf("Foo a:%d b:%d\n", foo.a, foo.b); Bar bar = bitcast(foo, Bar); diff --git a/resources/testfragments/diagnostic.c3 b/resources/testfragments/diagnostic.c3 index 75d0d10d2..175203e87 100644 --- a/resources/testfragments/diagnostic.c3 +++ b/resources/testfragments/diagnostic.c3 @@ -4,9 +4,11 @@ struct Overalign double[<33>] x; } +def Olist = List(); + fn void main() { - List() l; + Olist l; Overalign y; for (int i = 0; i < 1000; i++) { diff --git a/src/compiler/linker.c b/src/compiler/linker.c index d67dec475..d05a5ac44 100644 --- a/src/compiler/linker.c +++ b/src/compiler/linker.c @@ -402,7 +402,11 @@ static void linker_setup_linux(const char ***args_ref, Linker linker_type) static void linker_setup_freebsd(const char ***args_ref, Linker linker_type) { - if (linker_type == LINKER_CC) return; + if (linker_type == LINKER_CC) { + linking_add_link(&compiler.linking, "m"); + linking_add_link(&compiler.linking, "pthread"); + return; + } if (is_no_pie(compiler.platform.reloc_model)) add_plain_arg("-no-pie"); if (is_pie(compiler.platform.reloc_model)) add_plain_arg("-pie"); if (compiler.platform.arch == ARCH_TYPE_X86_64) add_plain_arg("--eh-frame-hdr"); diff --git a/src/utils/cpus.c b/src/utils/cpus.c index 111da76ca..7ffe4a795 100644 --- a/src/utils/cpus.c +++ b/src/utils/cpus.c @@ -8,7 +8,7 @@ int cpus(void) GetSystemInfo(&sysinfo); return sysinfo.dwNumberOfProcessors; } -#elif __APPLE__ || defined(__linux__) +#elif __APPLE__ || defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) #include int cpus(void) { @@ -20,4 +20,4 @@ int cpus(void) REMINDER("Implement processor count for OS"); return 1; } -#endif \ No newline at end of file +#endif