commit e53522e9bf0377e3b3629e3706e00ac60d0a1510
parent 8c1d3ba103dad32d474bcfeb394c629ed00649ea
Author: Ryan Sepassi <rsepassi@gmail.com>
Date: Sun, 24 May 2026 06:26:51 -0700
cc: --sysroot triggers hosted mode; add freestanding math.h
Two changes that let cfree build itself through the real Makefile with
`CC=cc` (not just the stage2_link.sh probe), exercising the full
GCC-subset flag set the Makefile passes (-O, -std, -W*, -isysroot,
-ffreestanding, -MMD/-MP).
- driver/cc.c: a sysroot on its own (--sysroot/-isysroot, when not
-ffreestanding/-nostdinc/-shared/-nostdlib) now engages the hosted
libc profile, matching clang/gcc. The hosted driver sources then find
<dlfcn.h> et al. AND get the feature-test defines (__GNUC__, __APPLE__,
__has_builtin, ...) the SDK headers branch on. -ffreestanding and
-nostdinc opt back out, keeping the freestanding rt/include set
standalone for the libcfree compile. Previously only -lc did this.
- rt/include/math.h: minimal freestanding declarations (sqrt/fma/fmaf
and companions). src/emu/cpu.c's rv64 interpreter implements guest
FSQRT/FMADD via host libm; it no longer needs the SDK's <math.h>
spliced in, so the freestanding lib build stays pure.
Bootstrap stays bitwise-reproducible (stage2 == stage3). test-elf,
test-smoke-{x64,rv64}, test-driver, test-parse, test-opt, test-toy pass.
Diffstat:
2 files changed, 74 insertions(+), 3 deletions(-)
diff --git a/driver/cc.c b/driver/cc.c
@@ -127,6 +127,8 @@ typedef struct CcOptions {
const char* linker_script; /* -T path */
uint16_t pe_subsystem; /* CfreePeSubsystem */
const char* sysroot; /* --sysroot / -isysroot */
+ int freestanding; /* -ffreestanding (suppresses sysroot headers) */
+ int nostdinc; /* -nostdinc (suppresses sysroot headers) */
const char* support_dir; /* --support-dir */
int probe_kind; /* CcProbeKind */
const char* probe_arg; /* -print-file-name= / -print-prog-name= */
@@ -1002,6 +1004,22 @@ static int cc_has_link_action(const CcOptions* o) {
o->dep_mode != CC_DEP_M && o->dep_mode != CC_DEP_MM;
}
+/* A sysroot on its own means "compile/link hosted against that root" — the
+ * same default clang and gcc take for -isysroot/--sysroot. Engage the hosted
+ * libc profile so the host headers, their feature-test defines (__GNUC__,
+ * __APPLE__, __has_builtin, ...) and (for link actions) the host C runtime are
+ * brought in. -ffreestanding and -nostdinc opt back out, keeping the
+ * freestanding rt/include set standalone; -shared and the -nostdlib family
+ * keep their existing meaning. The Windows-COFF default profile and an explicit
+ * -lc already set the flag, so this is a no-op in those cases. */
+static void cc_enable_hosted_for_sysroot(CcOptions* o) {
+ if (o->wants_hosted_libc || o->shared) return;
+ if (!o->sysroot || !o->sysroot[0]) return;
+ if (o->freestanding || o->nostdinc) return;
+ if (o->no_stdlib || o->no_defaultlibs) return;
+ o->wants_hosted_libc = 1;
+}
+
static void cc_apply_default_hosted_profile(CcOptions* o) {
if (o->target.os != CFREE_OS_WINDOWS || o->target.obj != CFREE_OBJ_COFF)
return;
@@ -1105,9 +1123,20 @@ static int cc_parse(int argc, char** argv, CcOptions* o) {
cc_log_ignored(a);
continue;
}
- if (driver_streq(a, "-ffreestanding") || driver_streq(a, "-fhosted") ||
- driver_streq(a, "-fno-builtin") || driver_streq(a, "-pipe") ||
- driver_streq(a, "-pthread") || driver_streq(a, "-nostdinc")) {
+ if (driver_streq(a, "-ffreestanding")) {
+ o->freestanding = 1;
+ continue;
+ }
+ if (driver_streq(a, "-fhosted")) {
+ o->freestanding = 0;
+ continue;
+ }
+ if (driver_streq(a, "-nostdinc")) {
+ o->nostdinc = 1;
+ continue;
+ }
+ if (driver_streq(a, "-fno-builtin") || driver_streq(a, "-pipe") ||
+ driver_streq(a, "-pthread")) {
cc_log_ignored(a);
continue;
}
@@ -1584,6 +1613,7 @@ static int cc_parse(int argc, char** argv, CcOptions* o) {
}
}
}
+ cc_enable_hosted_for_sysroot(o);
cc_apply_default_hosted_profile(o);
if (cc_apply_hosted_profile(o) != 0) return 1;
return 0;
diff --git a/rt/include/math.h b/rt/include/math.h
@@ -0,0 +1,41 @@
+/* math.h -- minimal freestanding declarations
+ *
+ * Declarations only; the definitions resolve from the host C library at
+ * link time (libSystem on Darwin, libm on ELF). cfree itself uses these
+ * in the rv64 interpreter (src/emu/cpu.c) to emulate FSQRT and the
+ * fused-multiply-add family with IEEE-correct rounding. */
+#ifndef CFREE_MATH_H
+#define CFREE_MATH_H
+
+double sqrt(double x);
+float sqrtf(float x);
+
+double fma(double x, double y, double z);
+float fmaf(float x, float y, float z);
+
+double fabs(double x);
+float fabsf(float x);
+
+double floor(double x);
+float floorf(float x);
+double ceil(double x);
+float ceilf(float x);
+double trunc(double x);
+float truncf(float x);
+double round(double x);
+float roundf(float x);
+double rint(double x);
+float rintf(float x);
+double nearbyint(double x);
+float nearbyintf(float x);
+
+double copysign(double x, double y);
+float copysignf(float x, float y);
+
+double scalbn(double x, int n);
+float scalbnf(float x, int n);
+
+double pow(double x, double y);
+float powf(float x, float y);
+
+#endif