kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

commit 33d98c62e5201d8ce5e5436096615915e6d7e6c3
parent e7429a445bea41bca5c1199bb98c3ca6ddced92e
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Mon, 25 May 2026 13:12:17 -0700

cc: support default symbol visibility

Diffstat:
Mdriver/cc.c | 15+++++++++++++++
Minclude/cfree/core.h | 1+
Mlang/c/c.c | 3++-
Mlang/c/parse/parse.c | 31++++++++++++++++++++++++++-----
Mlang/c/parse/parse.h | 2+-
Mlang/c/parse/parse_priv.h | 1+
6 files changed, 46 insertions(+), 7 deletions(-)

diff --git a/driver/cc.c b/driver/cc.c @@ -132,6 +132,7 @@ typedef struct CcOptions { uint16_t pe_subsystem; /* CfreePeSubsystem */ const char* sysroot; /* --sysroot / -isysroot */ int freestanding; /* -ffreestanding (suppresses sysroot headers) */ + uint8_t default_visibility; /* CfreeSymVis; -fvisibility=... */ int nostdinc; /* -nostdinc (suppresses sysroot headers) */ const char* support_dir; /* --support-dir */ int probe_kind; /* CcProbeKind */ @@ -1154,6 +1155,19 @@ static int cc_parse(int argc, char** argv, CcOptions* o) { o->freestanding = 1; continue; } + if (driver_streq(a, "-fvisibility=hidden")) { + o->default_visibility = CFREE_SV_HIDDEN; + continue; + } + if (driver_streq(a, "-fvisibility=default")) { + o->default_visibility = CFREE_SV_DEFAULT; + continue; + } + if (driver_strneq(a, "-fvisibility=", 13)) { + driver_errf(CC_TOOL, "unsupported visibility: %.*s", + CFREE_SLICE_ARG(cfree_slice_cstr(a + 13))); + return 1; + } if (driver_streq(a, "-fhosted")) { o->freestanding = 0; continue; @@ -2089,6 +2103,7 @@ static void cc_fill_c_opts(const CcOptions* o, const CfreePreprocessOptions* pp, copts->code.opt_level = o->syntax_only ? 0 : o->opt_level; copts->code.debug_info = o->debug_info; copts->code.check_only = o->syntax_only ? true : false; + copts->code.default_visibility = o->default_visibility; copts->code.emit_c_source = o->emit_c_source ? true : false; copts->code.emit_asm_source = o->emit_asm_source ? true : false; copts->code.epoch = o->epoch; diff --git a/include/cfree/core.h b/include/cfree/core.h @@ -198,6 +198,7 @@ typedef struct CfreeCodeOptions { /* Run the frontend and CG validation path without emitting target code. * Drivers use this for syntax/semantic checking modes. */ bool check_only; + uint8_t default_visibility; /* CfreeSymVis; 0 => CFREE_SV_DEFAULT */ /* When set, CG emits portable C source instead of machine-code bytes. * The TU is still target-locked: the emitted source uses the configured * triple's struct layouts and pointer width. Forces opt_level=0. diff --git a/lang/c/c.c b/lang/c/c.c @@ -116,7 +116,8 @@ static CfreeStatus c_frontend_compile( cfree_frontend_metrics_scope_end(c, "compile.c.pp_push_input"); cfree_frontend_metrics_scope_begin(c, "compile.c.parse_codegen"); - parse_c(c, pool, pp, decls, cg); + parse_c(c, pool, pp, decls, cg, + (CfreeSymVis)opts->code.default_visibility); cfree_frontend_metrics_scope_end(c, "compile.c.parse_codegen"); cfree_frontend_metrics_scope_begin(c, "compile.c.cleanup"); diff --git a/lang/c/parse/parse.c b/lang/c/parse/parse.c @@ -820,7 +820,7 @@ static void parse_init_declarator(Parser* p, const DeclSpecs* specs) { decl_in.loc = loc; decl_in.storage = DS_EXTERN; decl_in.linkage = DL_EXTERNAL; - decl_in.visibility = SV_DEFAULT; + decl_in.visibility = p->default_visibility; decl_in.flags = specs->flags & DF_THREAD; attr_list_to_decl(p->c, p->decls, specs->attrs, &decl_in); did = decl_declare(p->decls, &decl_in); @@ -1100,7 +1100,8 @@ static SymEntry* declare_function(Parser* p, Sym fname, const Type* fn_ty, : DS_EXTERN; decl_in.linkage = (decl_in.storage == DS_STATIC) ? DL_INTERNAL : DL_EXTERNAL; - decl_in.visibility = SV_DEFAULT; + decl_in.visibility = + decl_in.linkage == DL_EXTERNAL ? p->default_visibility : SV_DEFAULT; attr_list_to_decl(p->c, p->decls, specs->attrs, &decl_in); attr_list_to_decl(p->c, p->decls, dattrs, &decl_in); did = decl_declare(p->decls, &decl_in); @@ -1310,7 +1311,11 @@ static void parse_external_decl(Parser* p) { alias.target = te->v.sym; alias.sym.bind = (fn_decl_flags & DF_WEAK) ? CFREE_SB_WEAK : CFREE_SB_GLOBAL; - alias.sym.visibility = CFREE_CG_VIS_DEFAULT; + { + const Decl* fd = decl_get(p->decls, fent->decl_id); + alias.sym.visibility = + fd ? (CfreeCgVisibility)fd->visibility : CFREE_CG_VIS_DEFAULT; + } if (cfree_cg_alias(p->cg, alias) == CFREE_CG_SYM_NONE) { const char* nm = cfree_sym_str(p->pool->c, fn_alias_target).s; compiler_panic(p->c, loc, "alias target '%.*s' is undefined", @@ -1368,7 +1373,8 @@ static void parse_external_decl(Parser* p) { decl_in.storage = DS_EXTERN; decl_in.linkage = DL_EXTERNAL; } - decl_in.visibility = SV_DEFAULT; + decl_in.visibility = + decl_in.linkage == DL_EXTERNAL ? p->default_visibility : SV_DEFAULT; decl_in.flags = specs.flags & DF_THREAD; attr_list_to_decl(p->c, p->decls, specs.attrs, &decl_in); attr_list_to_decl(p->c, p->decls, dattrs, &decl_in); @@ -1476,7 +1482,21 @@ static void parse_translation_unit(Parser* p) { * Entry point * ============================================================ */ -void parse_c(Compiler* c, Pool* pool, Pp* pp, DeclTable* decls, CG* cg) { +static u8 parser_default_visibility(CfreeSymVis vis) { + switch (vis) { + case CFREE_SV_HIDDEN: + case CFREE_SV_INTERNAL: + return SV_HIDDEN; + case CFREE_SV_PROTECTED: + return SV_PROTECTED; + case CFREE_SV_DEFAULT: + default: + return SV_DEFAULT; + } +} + +void parse_c(Compiler* c, Pool* pool, Pp* pp, DeclTable* decls, CG* cg, + CfreeSymVis default_visibility) { Parser p; CKw i; @@ -1487,6 +1507,7 @@ void parse_c(Compiler* c, Pool* pool, Pp* pp, DeclTable* decls, CG* cg) { p.cg = cg; p.abi = c; p.pool = pool; + p.default_visibility = parser_default_visibility(default_visibility); for (i = (CKw)1; i < KW_COUNT; ++i) { p.kw_sym[i] = cfree_sym_intern(p.pool->c, cfree_slice_cstr(kw_names[i])); diff --git a/lang/c/parse/parse.h b/lang/c/parse/parse.h @@ -7,6 +7,6 @@ /* C11 frontend. Reads preprocessed tokens, records C declarations, and drives * the public CG API for executable code and object data. */ -void parse_c(Compiler*, Pool*, Pp*, DeclTable*, CG*); +void parse_c(Compiler*, Pool*, Pp*, DeclTable*, CG*, CfreeSymVis); #endif diff --git a/lang/c/parse/parse_priv.h b/lang/c/parse/parse_priv.h @@ -194,6 +194,7 @@ typedef struct Parser { CG* cg; TargetABI* abi; Pool* pool; + u8 default_visibility; /* SymVis */ const Type** cg_type_stack; u8* cg_value_flags;