kit

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

commit a976537e1fa0e161c3acad8c8b347c4171813800
parent de9bfacea7ed2f358f9838a35809d2a56cd1c990
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Tue,  9 Jun 2026 19:01:56 -0700

driver: share cc/build link-input model via lib/link_inputs

cc and build-* each carried a byte-identical copy of the link-input model
(link items + object/archive/dso/lib arrays) and its bookkeeping. Hoist it
into a shared DriverLinkInputSet, embedded in both option structs like the
existing DriverCflags/DriverLinkFlags sub-structs.

driver/lib/link_inputs.{c,h}: types (DriverLinkKind/Item, Driver{Archive,Dso}
Input, DriverPendingLib) + DriverLinkInputSet and helpers (init/fini, push/
insert, append_hosted, insert_runtime_archive, resolve_pending, append_windows
_lib_dirs, apply_hosted, is_dso_path). Each driver keeps only its tool-specific
state (cc: sources/deps/probes/path-maps; build: groups/scopes) and delegates
the hosted-libc profile body through a thin guard wrapper.

Also drop the duplicated cc_/build_parse_u64 (use driver_parse_u64) and
record_mcmodel (new driver_record_mcmodel in target.c).

~700 lines of duplicated logic collapse to one copy. cc.c -588, build.c -547.

Verified: make bin clean; test-driver-build 76/0, test-driver-cc 106/1,
test-link 124/0, test-driver-ar, smoke-x64/rv64 green. The one cc failure
(ld-hosted-lc-sysroot) is pre-existing (confirmed identical on HEAD): a macOS
host can't emit ELF shared libs via `kit ld -shared` in the test's setup.

Diffstat:
Mdriver/cmd/build.c | 547+++++++++++++++++++------------------------------------------------------------
Mdriver/cmd/cc.c | 588+++++++++++++++++++------------------------------------------------------------
Mdriver/driver.h | 6++++++
Adriver/lib/link_inputs.c | 267+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adriver/lib/link_inputs.h | 154+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mdriver/lib/target.c | 19+++++++++++++++++++
Mmk/driver_srcs.mk | 1+
7 files changed, 718 insertions(+), 864 deletions(-)

diff --git a/driver/cmd/build.c b/driver/cmd/build.c @@ -13,6 +13,7 @@ #include "lib_resolve.h" #include "link_engine.h" #include "link_flags.h" +#include "link_inputs.h" #include "runtime.h" /* `kit build-exe` / `build-lib` / `build-obj` — the kit-native build verbs. @@ -54,50 +55,14 @@ typedef enum BuildEmit { BUILD_EMIT_IR, } BuildEmit; -typedef enum BuildLinkKind { - BUILD_LINK_SOURCE, - BUILD_LINK_OBJECT, - BUILD_LINK_ARCHIVE, - BUILD_LINK_DSO, - BUILD_LINK_LIB, -} BuildLinkKind; - -typedef struct BuildLinkItem { - uint8_t kind; /* BuildLinkKind */ - uint8_t pad[3]; - uint32_t index; -} BuildLinkItem; +/* The link-input model (link items + object/archive/dso/lib arrays) is shared + * with the cc driver; see driver/lib/link_inputs.h. */ typedef struct BuildSource { const char* path; /* argv-borrowed */ uint32_t group; /* index into o->groups[]; 0 = global/bare baseline */ } BuildSource; -typedef struct BuildArchiveInput { - const char* path; - int owned; - size_t owned_size; - uint8_t whole_archive; - uint8_t link_mode; - uint8_t group_id; - uint8_t pad; -} BuildArchiveInput; - -typedef struct BuildDsoInput { - const char* path; - int owned; - size_t owned_size; -} BuildDsoInput; - -typedef struct BuildPendingLib { - const char* name; - uint8_t whole_archive; - uint8_t link_mode; - uint8_t group_id; - uint8_t resolved_kind; /* BuildLinkKind: ARCHIVE or DSO */ - uint32_t resolved_index; -} BuildPendingLib; - /* One -X<lang> frontend flag token, scoped to a language. */ typedef struct BuildFeFlag { uint8_t lang; /* KitLanguage */ @@ -172,8 +137,6 @@ typedef struct BuildOptions { int no_startfiles; int wants_hosted_libc; DriverHostedPlan hosted; - char* owned_sysroot_lib_dir; - size_t owned_sysroot_lib_dir_size; /* Sources + compile-flag scopes. */ BuildSource* sources; @@ -182,64 +145,17 @@ typedef struct BuildOptions { uint32_t ngroups; uint32_t cur_group; /* scope for newly seen sources */ - /* Link inputs (build-exe). */ - const char** object_files; - uint32_t nobject_files; - BuildArchiveInput* archives; - uint32_t narchives; - BuildDsoInput* dsos; - uint32_t ndsos; - const char** lib_search_paths; - uint32_t nlib_search_paths; - BuildPendingLib* pending_libs; - uint32_t npending_libs; - BuildLinkItem* link_items; - uint32_t nlink_items; - uint8_t cur_whole_archive; - uint8_t cur_link_mode; - uint8_t cur_group_id; + /* Shared link-input model (build-exe / dynamic build-lib): + * object/archive/dso/ lib arrays, the ordered link item list, -L search + * paths, and the owned + * `<sysroot>/lib` Windows slot. */ + DriverLinkInputSet inputs; } BuildOptions; /* ===================================================================== */ /* small parse helpers */ /* ===================================================================== */ -static int build_parse_u64(const char* s, uint64_t* out) { - uint64_t v = 0; - int any = 0; - if (!s) return 1; - while (*s) { - unsigned d; - if (*s < '0' || *s > '9') return 1; - d = (unsigned)(*s - '0'); - if (v > (UINT64_MAX - d) / 10u) return 1; - v = v * 10u + d; - any = 1; - s++; - } - if (!any) return 1; - *out = v; - return 0; -} - -static int build_record_mcmodel(BuildOptions* o, const char* val) { - if (driver_streq(val, "small") || driver_streq(val, "medlow")) { - o->target.code_model = KIT_CM_SMALL; - return 0; - } - if (driver_streq(val, "medium") || driver_streq(val, "medany")) { - o->target.code_model = KIT_CM_MEDIUM; - return 0; - } - if (driver_streq(val, "large")) { - o->target.code_model = KIT_CM_LARGE; - return 0; - } - driver_errf(o->tool, "unknown -mcmodel value: %.*s", - KIT_SLICE_ARG(kit_slice_cstr(val))); - return 1; -} - static int build_lang_from_name(const char* name, KitLanguage* out) { /* Resolve off the compile-time default frontend set (no compiler exists at * arg-parse time). Value-equivalent to the former explicit map: @@ -271,21 +187,12 @@ static int build_alloc(BuildOptions* o, int argc) { o->argv_bound = bound; o->sources = driver_alloc_zeroed(o->env, bound * sizeof(*o->sources)); o->groups = driver_alloc_zeroed(o->env, bound * sizeof(*o->groups)); - o->object_files = - driver_alloc_zeroed(o->env, bound * sizeof(*o->object_files)); - o->archives = driver_alloc_zeroed(o->env, bound * sizeof(*o->archives)); - o->dsos = driver_alloc_zeroed(o->env, bound * sizeof(*o->dsos)); - o->lib_search_paths = - driver_alloc_zeroed(o->env, bound * sizeof(*o->lib_search_paths)); - o->pending_libs = - driver_alloc_zeroed(o->env, bound * sizeof(*o->pending_libs)); - o->link_items = driver_alloc_zeroed(o->env, bound * sizeof(*o->link_items)); - if (!o->sources || !o->groups || !o->object_files || !o->archives || - !o->dsos || !o->lib_search_paths || !o->pending_libs || !o->link_items) { + if (!o->sources || !o->groups) { driver_errf(o->tool, "out of memory"); return 1; } - o->cur_link_mode = KIT_LM_DEFAULT; + if (driver_link_inputs_init(&o->inputs, o->env, o->tool, bound) != 0) + return 1; /* groups[0] is the global / bare baseline. */ o->ngroups = 1; if (driver_link_flags_init(&o->link, o->env, o->tool, (uint32_t)bound) != 0 || @@ -300,13 +207,6 @@ static int build_alloc(BuildOptions* o, int argc) { static void build_release(BuildOptions* o) { uint32_t i; size_t bound = o->argv_bound; - for (i = 0; i < o->narchives; ++i) - if (o->archives[i].owned) - driver_free(o->env, (void*)o->archives[i].path, - o->archives[i].owned_size); - for (i = 0; i < o->ndsos; ++i) - if (o->dsos[i].owned) - driver_free(o->env, (void*)o->dsos[i].path, o->dsos[i].owned_size); for (i = 0; i < o->ngroups; ++i) { BuildGroup* g = &o->groups[i]; if (g->cf_inited) driver_cflags_fini(&g->cf, o->env); @@ -317,100 +217,12 @@ static void build_release(BuildOptions* o) { driver_free(o->env, g->m_def, g->m_def_cap * sizeof(*g->m_def)); if (g->m_und) driver_free(o->env, g->m_und, g->m_nund * sizeof(*g->m_und)); } - if (o->owned_sysroot_lib_dir) - driver_free(o->env, o->owned_sysroot_lib_dir, - o->owned_sysroot_lib_dir_size); + driver_link_inputs_fini(&o->inputs); driver_hosted_plan_fini(o->env, &o->hosted); driver_link_flags_fini(&o->link); driver_target_features_fini(&o->target_features, o->env); if (o->sources) driver_free(o->env, o->sources, bound * sizeof(*o->sources)); if (o->groups) driver_free(o->env, o->groups, bound * sizeof(*o->groups)); - if (o->object_files) - driver_free(o->env, o->object_files, bound * sizeof(*o->object_files)); - if (o->archives) - driver_free(o->env, o->archives, bound * sizeof(*o->archives)); - if (o->dsos) driver_free(o->env, o->dsos, bound * sizeof(*o->dsos)); - if (o->lib_search_paths) - driver_free(o->env, o->lib_search_paths, - bound * sizeof(*o->lib_search_paths)); - if (o->pending_libs) - driver_free(o->env, o->pending_libs, bound * sizeof(*o->pending_libs)); - if (o->link_items) - driver_free(o->env, o->link_items, bound * sizeof(*o->link_items)); -} - -/* ===================================================================== */ -/* link-item bookkeeping (build-exe) */ -/* ===================================================================== */ - -static void build_push_link_item(BuildOptions* o, uint8_t kind, - uint32_t index) { - BuildLinkItem* it = &o->link_items[o->nlink_items++]; - it->kind = kind; - it->index = index; -} - -static void build_insert_link_item(BuildOptions* o, uint32_t pos, uint8_t kind, - uint32_t index) { - uint32_t i; - if (pos > o->nlink_items) pos = o->nlink_items; - for (i = o->nlink_items; i > pos; --i) - o->link_items[i] = o->link_items[i - 1u]; - o->link_items[pos].kind = kind; - o->link_items[pos].index = index; - o->nlink_items++; -} - -static int build_append_hosted_input(BuildOptions* o, - const DriverHostedInput* in, - uint32_t insert_pos, int insert) { - uint32_t index; - uint8_t kind; - switch ((DriverHostedInputKind)in->kind) { - case DRIVER_HOSTED_INPUT_OBJECT: - index = o->nobject_files++; - o->object_files[index] = in->path; - kind = BUILD_LINK_OBJECT; - break; - case DRIVER_HOSTED_INPUT_ARCHIVE: { - BuildArchiveInput* ar = &o->archives[o->narchives++]; - ar->path = in->path; - ar->link_mode = KIT_LM_DEFAULT; - index = o->narchives - 1u; - kind = BUILD_LINK_ARCHIVE; - break; - } - case DRIVER_HOSTED_INPUT_DSO: { - BuildDsoInput* d = &o->dsos[o->ndsos++]; - d->path = in->path; - index = o->ndsos - 1u; - kind = BUILD_LINK_DSO; - break; - } - default: - driver_errf(o->tool, "internal error: unknown hosted input kind"); - return 1; - } - if (insert) - build_insert_link_item(o, insert_pos, kind, index); - else - build_push_link_item(o, kind, index); - return 0; -} - -static void build_insert_runtime_archive(BuildOptions* o, - DriverRuntimeArchive* rt, - uint32_t insert_pos) { - BuildArchiveInput* ar = &o->archives[o->narchives++]; - ar->path = rt->path; - ar->owned = 1; - ar->owned_size = rt->path_size; - ar->whole_archive = rt->whole_archive; - ar->link_mode = rt->link_mode; - ar->group_id = rt->group_id; - rt->path = NULL; - rt->path_size = 0; - build_insert_link_item(o, insert_pos, BUILD_LINK_ARCHIVE, o->narchives - 1u); } /* ===================================================================== */ @@ -423,11 +235,6 @@ static void build_insert_runtime_archive(BuildOptions* o, * the helper excludes it. */ static int build_is_source(const char* s) { return driver_path_is_source(s); } -static int build_is_dso(const char* s) { - return driver_has_suffix(s, ".so") || driver_has_suffix(s, ".dylib") || - driver_has_suffix(s, ".tbd"); -} - /* The language forced (via -x) for sources in group `gi`: the group's own -x, * else the global baseline's, else -1 (resolve by suffix). */ static int build_scope_forced_lang(const BuildOptions* o, uint32_t gi) { @@ -446,23 +253,25 @@ static int build_classify_positional(BuildOptions* o, const char* a) { /* Explicit link-input suffixes are always link inputs — never reinterpreted * as sources, even when -x forces a language. */ if (driver_has_suffix(a, ".o") || driver_has_suffix(a, ".obj")) { - o->object_files[o->nobject_files++] = a; - build_push_link_item(o, BUILD_LINK_OBJECT, o->nobject_files - 1u); + o->inputs.object_files[o->inputs.nobject_files++] = a; + driver_link_inputs_push(&o->inputs, DRIVER_LINK_OBJECT, + o->inputs.nobject_files - 1u); return 0; } if (driver_has_suffix(a, ".a")) { - BuildArchiveInput* ar = &o->archives[o->narchives++]; + DriverArchiveInput* ar = &o->inputs.archives[o->inputs.narchives++]; ar->path = a; - ar->whole_archive = o->cur_whole_archive; - ar->link_mode = o->cur_link_mode; - ar->group_id = o->cur_group_id; - build_push_link_item(o, BUILD_LINK_ARCHIVE, o->narchives - 1u); + ar->whole_archive = o->inputs.cur_whole_archive; + ar->link_mode = o->inputs.cur_link_mode; + ar->group_id = o->inputs.cur_group_id; + driver_link_inputs_push(&o->inputs, DRIVER_LINK_ARCHIVE, + o->inputs.narchives - 1u); return 0; } - if (build_is_dso(a)) { - BuildDsoInput* d = &o->dsos[o->ndsos++]; + if (driver_is_dso_path(a)) { + DriverDsoInput* d = &o->inputs.dsos[o->inputs.ndsos++]; d->path = a; - build_push_link_item(o, BUILD_LINK_DSO, o->ndsos - 1u); + driver_link_inputs_push(&o->inputs, DRIVER_LINK_DSO, o->inputs.ndsos - 1u); return 0; } /* Otherwise a source: a recognized source suffix, or any file at all when a @@ -472,7 +281,7 @@ static int build_classify_positional(BuildOptions* o, const char* a) { BuildSource* s = &o->sources[o->nsources]; s->path = a; s->group = o->cur_group; - build_push_link_item(o, BUILD_LINK_SOURCE, o->nsources); + driver_link_inputs_push(&o->inputs, DRIVER_LINK_SOURCE, o->nsources); o->nsources++; return 0; } @@ -693,7 +502,7 @@ static int build_parse(int argc, char** argv, BuildOptions* o) { } if (driver_strneq(a, "-fmax-errors=", 13)) { uint64_t v; - if (build_parse_u64(a + 13, &v) != 0 || v > 0xFFFFFFFFu) { + if (driver_parse_u64(a + 13, &v) != 0 || v > 0xFFFFFFFFu) { driver_errf(o->tool, "-fmax-errors= requires a non-negative integer"); return 1; } @@ -779,7 +588,7 @@ static int build_parse(int argc, char** argv, BuildOptions* o) { if (driver_streq(a, "-static")) { o->static_link = 1; o->target.pic = KIT_PIC_NONE; - o->cur_link_mode = KIT_LM_STATIC; + o->inputs.cur_link_mode = KIT_LM_STATIC; continue; } if (driver_streq(a, "-dynamic")) { @@ -809,7 +618,7 @@ static int build_parse(int argc, char** argv, BuildOptions* o) { driver_errf(o->tool, "-L requires an argument"); return 1; } - o->lib_search_paths[o->nlib_search_paths++] = dir; + o->inputs.lib_search_paths[o->inputs.nlib_search_paths++] = dir; continue; } if (driver_strneq(a, "-l", 2)) { @@ -823,12 +632,14 @@ static int build_parse(int argc, char** argv, BuildOptions* o) { continue; } { - BuildPendingLib* pl = &o->pending_libs[o->npending_libs++]; + DriverPendingLib* pl = + &o->inputs.pending_libs[o->inputs.npending_libs++]; pl->name = name; - pl->whole_archive = o->cur_whole_archive; - pl->link_mode = o->cur_link_mode; - pl->group_id = o->cur_group_id; - build_push_link_item(o, BUILD_LINK_LIB, o->npending_libs - 1u); + pl->whole_archive = o->inputs.cur_whole_archive; + pl->link_mode = o->inputs.cur_link_mode; + pl->group_id = o->inputs.cur_group_id; + driver_link_inputs_push(&o->inputs, DRIVER_LINK_LIB, + o->inputs.npending_libs - 1u); } continue; } @@ -873,7 +684,7 @@ static int build_parse(int argc, char** argv, BuildOptions* o) { continue; } if (driver_strneq(a, "-mcmodel=", 9)) { - if (build_record_mcmodel(o, a + 9) != 0) return 1; + if (driver_record_mcmodel(&o->target, o->tool, a + 9) != 0) return 1; continue; } @@ -957,48 +768,6 @@ static int build_is_link_output(const BuildOptions* o) { return o->kind == BUILD_OUT_EXE || (o->kind == BUILD_OUT_LIB && o->dynamic); } -static int build_resolve_pending_libs(BuildOptions* o) { - uint32_t i; - for (i = 0; i < o->npending_libs; ++i) { - BuildPendingLib* pl = &o->pending_libs[i]; - char* p; - size_t sz; - LibResolveKind kind; - LibResolveMode mode = (o->static_link || pl->link_mode == KIT_LM_STATIC) - ? LIB_RESOLVE_STATIC_ONLY - : LIB_RESOLVE_DYNAMIC_PREFER; - LibResolveOS resolve_os = (o->target.os == KIT_OS_WINDOWS) - ? LIB_RESOLVE_OS_WINDOWS - : LIB_RESOLVE_OS_POSIX; - if (driver_lib_resolve_for_os(o->env, pl->name, mode, resolve_os, - o->lib_search_paths, o->nlib_search_paths, &p, - &sz, &kind) != 0) { - driver_errf(o->tool, "library not found: -l%.*s", - KIT_SLICE_ARG(kit_slice_cstr(pl->name))); - return 1; - } - if (kind == LIB_RESOLVE_KIND_SHARED || kind == LIB_RESOLVE_KIND_TBD) { - BuildDsoInput* d = &o->dsos[o->ndsos++]; - d->path = p; - d->owned = 1; - d->owned_size = sz; - pl->resolved_kind = BUILD_LINK_DSO; - pl->resolved_index = o->ndsos - 1u; - } else { - BuildArchiveInput* ar = &o->archives[o->narchives++]; - ar->path = p; - ar->owned = 1; - ar->owned_size = sz; - ar->whole_archive = pl->whole_archive; - ar->link_mode = pl->link_mode; - ar->group_id = pl->group_id; - pl->resolved_kind = BUILD_LINK_ARCHIVE; - pl->resolved_index = o->narchives - 1u; - } - } - return 0; -} - /* A sysroot on its own engages the hosted libc profile (matching clang/gcc). * -ffreestanding / -nostdinc / -nostdlib opt back out; -dynamic (shared) keeps * its standalone meaning. */ @@ -1018,84 +787,17 @@ static void build_apply_default_hosted_profile(BuildOptions* o) { } static int build_apply_hosted_profile(BuildOptions* o) { - DriverHostedRequest req; - uint32_t i; - uint32_t insert_pos = 0; if (!o->wants_hosted_libc || o->shared) return 0; if (o->no_stdlib || o->no_defaultlibs) { driver_errf(o->tool, "-lc hosted expansion is disabled by -nostdlib/-nodefaultlibs"); return 1; } - { - DriverHostedRequest z = {0}; - req = z; - } - req.env = o->env; - req.tool = o->tool; - req.target = o->target; - req.sysroot = o->sysroot; - req.static_link = o->static_link; - req.link_inputs = 1; - if (driver_hosted_resolve(&req, &o->hosted) != 0) return 1; - for (i = 0; i < o->hosted.nsystem_includes; ++i) - o->groups[0] - .cf.system_include_dirs[o->groups[0].cf.nsystem_include_dirs++] = - o->hosted.system_includes[i]; - for (i = 0; i < o->hosted.ndefines; ++i) - o->groups[0].cf.defines[o->groups[0].cf.ndefines++] = o->hosted.defines[i]; - /* Add hosted lib search dirs so user -l flags (-lm, -lpthread, etc.) can be - * resolved. The strings are owned by o->hosted and outlive lib_search_paths. - * Insert before any user -L dirs so sysroot libs take precedence. */ - for (i = 0; i < o->hosted.nlib_search_dirs; ++i) - o->lib_search_paths[o->nlib_search_paths++] = o->hosted.lib_search_dirs[i]; - for (i = 0; i < o->hosted.nbefore; ++i) { - if (o->no_startfiles) break; - if (build_append_hosted_input(o, &o->hosted.before[i], insert_pos, 1) != 0) - return 1; - insert_pos++; - } - for (i = 0; i < o->hosted.nafter; ++i) - if (build_append_hosted_input(o, &o->hosted.after[i], 0, 0) != 0) return 1; - for (i = 0; i < o->hosted.nfinal; ++i) { - if (o->no_startfiles) break; - if (build_append_hosted_input(o, &o->hosted.final[i], 0, 0) != 0) return 1; - } - if (!o->link.interp_path && o->hosted.interp_path) - o->link.interp_path = o->hosted.interp_path; - return 0; -} - -/* Append `<sysroot>/lib` to the search path for Windows targets (mirrors cc). - */ -static int build_append_windows_lib_dirs(BuildOptions* o) { - const char* sysroot = o->sysroot; - char* joined; - size_t srlen, need_slash, bytes, off = 0; - if (!driver_target_needs_sysroot_libdir(o->target)) return 0; - if (!sysroot || !sysroot[0]) { - sysroot = driver_getenv("KIT_SYSROOT"); - if (!sysroot || !sysroot[0]) return 0; - o->sysroot = sysroot; - } - srlen = driver_strlen(sysroot); - need_slash = (srlen > 0 && sysroot[srlen - 1] != '/') ? 1u : 0u; - bytes = srlen + need_slash + 3u + 1u; - joined = driver_alloc(o->env, bytes); - if (!joined) { - driver_errf(o->tool, "out of memory"); - return 1; - } - driver_memcpy(joined + off, sysroot, srlen); - off += srlen; - if (need_slash) joined[off++] = '/'; - driver_memcpy(joined + off, "lib", 3); - off += 3; - joined[off] = '\0'; - o->owned_sysroot_lib_dir = joined; - o->owned_sysroot_lib_dir_size = bytes; - o->lib_search_paths[o->nlib_search_paths++] = joined; - return 0; + /* build-* always links (or archives) its outputs, so the crt inputs always + * apply: pass link_action = 1. */ + return driver_link_inputs_apply_hosted( + &o->inputs, &o->hosted, &o->groups[0].cf, &o->link, o->target, o->sysroot, + o->static_link, o->no_startfiles, 1); } /* ===================================================================== */ @@ -1253,9 +955,10 @@ static int build_compile_source(BuildOptions* o, KitCompiler* compiler, if (fe_n) { if (kit_frontend_parse_options(compiler, lang, (int)fe_n, fe_argv, &lang_extra) != KIT_OK) { - driver_errf(o->tool, "unsupported -X%.*s frontend flag: %.*s", - KIT_SLICE_ARG(kit_slice_cstr(kit_language_name(compiler, lang))), - KIT_SLICE_ARG(kit_slice_cstr(fe_argv[0]))); + driver_errf( + o->tool, "unsupported -X%.*s frontend flag: %.*s", + KIT_SLICE_ARG(kit_slice_cstr(kit_language_name(compiler, lang))), + KIT_SLICE_ARG(kit_slice_cstr(fe_argv[0]))); goto out; } } @@ -1488,48 +1191,52 @@ static int build_run_link(BuildOptions* o, KitCompiler* compiler, driver_alloc_zeroed(env, o->nsources * sizeof(*source_order_keep)); if (!objs || !source_obj_index || !source_order_keep) goto oom; } - if (o->nobject_files) { - obj_lf = driver_alloc_zeroed(env, o->nobject_files * sizeof(*obj_lf)); - obj_in = driver_alloc_zeroed(env, o->nobject_files * sizeof(*obj_in)); - obj_names = driver_alloc_zeroed(env, o->nobject_files * sizeof(*obj_names)); + if (o->inputs.nobject_files) { + obj_lf = + driver_alloc_zeroed(env, o->inputs.nobject_files * sizeof(*obj_lf)); + obj_in = + driver_alloc_zeroed(env, o->inputs.nobject_files * sizeof(*obj_in)); + obj_names = + driver_alloc_zeroed(env, o->inputs.nobject_files * sizeof(*obj_names)); if (!obj_lf || !obj_in || !obj_names) goto oom; } - if (o->narchives) { - arch_lf = driver_alloc_zeroed(env, o->narchives * sizeof(*arch_lf)); - arch_in = driver_alloc_zeroed(env, o->narchives * sizeof(*arch_in)); + if (o->inputs.narchives) { + arch_lf = driver_alloc_zeroed(env, o->inputs.narchives * sizeof(*arch_lf)); + arch_in = driver_alloc_zeroed(env, o->inputs.narchives * sizeof(*arch_in)); if (!arch_lf || !arch_in) goto oom; } - if (o->ndsos) { - dso_lf = driver_alloc_zeroed(env, o->ndsos * sizeof(*dso_lf)); - dso_in = driver_alloc_zeroed(env, o->ndsos * sizeof(*dso_in)); - dso_names = driver_alloc_zeroed(env, o->ndsos * sizeof(*dso_names)); + if (o->inputs.ndsos) { + dso_lf = driver_alloc_zeroed(env, o->inputs.ndsos * sizeof(*dso_lf)); + dso_in = driver_alloc_zeroed(env, o->inputs.ndsos * sizeof(*dso_in)); + dso_names = driver_alloc_zeroed(env, o->inputs.ndsos * sizeof(*dso_names)); if (!dso_lf || !dso_in || !dso_names) goto oom; } - if (o->nlink_items) { - order = driver_alloc_zeroed(env, o->nlink_items * sizeof(*order)); + if (o->inputs.nlink_items) { + order = driver_alloc_zeroed(env, o->inputs.nlink_items * sizeof(*order)); if (!order) goto oom; } - for (i = 0; i < o->nobject_files; ++i) { - if (driver_load_bytes(io, o->tool, o->object_files[i], &obj_lf[i], + for (i = 0; i < o->inputs.nobject_files; ++i) { + if (driver_load_bytes(io, o->tool, o->inputs.object_files[i], &obj_lf[i], &obj_in[i]) != 0) goto out; - obj_names[i] = kit_slice_cstr(o->object_files[i]); + obj_names[i] = kit_slice_cstr(o->inputs.object_files[i]); } - for (i = 0; i < o->narchives; ++i) { - if (driver_load_bytes(io, o->tool, o->archives[i].path, &arch_lf[i], + for (i = 0; i < o->inputs.narchives; ++i) { + if (driver_load_bytes(io, o->tool, o->inputs.archives[i].path, &arch_lf[i], &arch_in[i].bytes) != 0) goto out; - arch_in[i].name = kit_slice_cstr(o->archives[i].path); - arch_in[i].link_mode = o->archives[i].link_mode; - arch_in[i].whole_archive = o->archives[i].whole_archive ? true : false; - arch_in[i].group_id = o->archives[i].group_id; - } - for (i = 0; i < o->ndsos; ++i) { - if (driver_load_bytes(io, o->tool, o->dsos[i].path, &dso_lf[i], + arch_in[i].name = kit_slice_cstr(o->inputs.archives[i].path); + arch_in[i].link_mode = o->inputs.archives[i].link_mode; + arch_in[i].whole_archive = + o->inputs.archives[i].whole_archive ? true : false; + arch_in[i].group_id = o->inputs.archives[i].group_id; + } + for (i = 0; i < o->inputs.ndsos; ++i) { + if (driver_load_bytes(io, o->tool, o->inputs.dsos[i].path, &dso_lf[i], &dso_in[i]) != 0) goto out; - dso_names[i] = kit_slice_cstr(o->dsos[i].path); + dso_names[i] = kit_slice_cstr(o->inputs.dsos[i].path); } if (o->link.linker_script) { KitSlice dummy; @@ -1564,35 +1271,38 @@ static int build_run_link(BuildOptions* o, KitCompiler* compiler, goto out; /* Translate the recorded link order into KitLinkInputOrder. */ - for (i = 0; i < o->nlink_items; ++i) { - const BuildLinkItem* item = &o->link_items[i]; + for (i = 0; i < o->inputs.nlink_items; ++i) { + const DriverLinkItem* item = &o->inputs.link_items[i]; KitLinkInputOrder* ord; - switch ((BuildLinkKind)item->kind) { - case BUILD_LINK_SOURCE: + switch ((DriverLinkKind)item->kind) { + case DRIVER_LINK_SOURCE: if (!source_order_keep[item->index]) continue; ord = &order[norder++]; ord->kind = KIT_LINK_INPUT_OBJ; ord->index = source_obj_index[item->index]; break; - case BUILD_LINK_OBJECT: + case DRIVER_LINK_SOURCE_MEMORY: + /* cc-only (in-memory stdin source); build never records it. */ + break; + case DRIVER_LINK_OBJECT: ord = &order[norder++]; ord->kind = KIT_LINK_INPUT_OBJ_BYTES; ord->index = item->index; break; - case BUILD_LINK_ARCHIVE: + case DRIVER_LINK_ARCHIVE: ord = &order[norder++]; ord->kind = KIT_LINK_INPUT_ARCHIVE; ord->index = item->index; break; - case BUILD_LINK_DSO: + case DRIVER_LINK_DSO: ord = &order[norder++]; ord->kind = KIT_LINK_INPUT_DSO; ord->index = item->index; break; - case BUILD_LINK_LIB: { - const BuildPendingLib* pl = &o->pending_libs[item->index]; + case DRIVER_LINK_LIB: { + const DriverPendingLib* pl = &o->inputs.pending_libs[item->index]; ord = &order[norder++]; - if (pl->resolved_kind == BUILD_LINK_DSO) { + if (pl->resolved_kind == DRIVER_LINK_DSO) { ord->kind = KIT_LINK_INPUT_DSO; ord->index = pl->resolved_index; } else { @@ -1618,12 +1328,12 @@ static int build_run_link(BuildOptions* o, KitCompiler* compiler, li.nobjs = nobjs; li.obj_names = obj_names; li.obj_bytes = obj_in; - li.nobj_bytes = o->nobject_files; + li.nobj_bytes = o->inputs.nobject_files; li.archives = arch_in; - li.narchives = o->narchives; + li.narchives = o->inputs.narchives; li.dso_names = dso_names; li.dso_bytes = dso_in; - li.ndsos = o->ndsos; + li.ndsos = o->inputs.ndsos; li.order = order; li.norder = norder; st = driver_link_engine_emit_with_lto(compiler, &lopts, &li, &pending_lto, @@ -1646,21 +1356,28 @@ out: driver_link_flags_free_rpath_slices(&o->link, rpath_slices); driver_release_bytes(io, &script_lf); if (arch_lf) - for (i = 0; i < o->narchives; ++i) driver_release_bytes(io, &arch_lf[i]); + for (i = 0; i < o->inputs.narchives; ++i) + driver_release_bytes(io, &arch_lf[i]); if (dso_lf) - for (i = 0; i < o->ndsos; ++i) driver_release_bytes(io, &dso_lf[i]); + for (i = 0; i < o->inputs.ndsos; ++i) driver_release_bytes(io, &dso_lf[i]); if (obj_lf) - for (i = 0; i < o->nobject_files; ++i) driver_release_bytes(io, &obj_lf[i]); - if (arch_in) driver_free(env, arch_in, o->narchives * sizeof(*arch_in)); - if (arch_lf) driver_free(env, arch_lf, o->narchives * sizeof(*arch_lf)); - if (dso_in) driver_free(env, dso_in, o->ndsos * sizeof(*dso_in)); - if (dso_names) driver_free(env, dso_names, o->ndsos * sizeof(*dso_names)); - if (dso_lf) driver_free(env, dso_lf, o->ndsos * sizeof(*dso_lf)); - if (order) driver_free(env, order, o->nlink_items * sizeof(*order)); - if (obj_in) driver_free(env, obj_in, o->nobject_files * sizeof(*obj_in)); + for (i = 0; i < o->inputs.nobject_files; ++i) + driver_release_bytes(io, &obj_lf[i]); + if (arch_in) + driver_free(env, arch_in, o->inputs.narchives * sizeof(*arch_in)); + if (arch_lf) + driver_free(env, arch_lf, o->inputs.narchives * sizeof(*arch_lf)); + if (dso_in) driver_free(env, dso_in, o->inputs.ndsos * sizeof(*dso_in)); + if (dso_names) + driver_free(env, dso_names, o->inputs.ndsos * sizeof(*dso_names)); + if (dso_lf) driver_free(env, dso_lf, o->inputs.ndsos * sizeof(*dso_lf)); + if (order) driver_free(env, order, o->inputs.nlink_items * sizeof(*order)); + if (obj_in) + driver_free(env, obj_in, o->inputs.nobject_files * sizeof(*obj_in)); if (obj_names) - driver_free(env, obj_names, o->nobject_files * sizeof(*obj_names)); - if (obj_lf) driver_free(env, obj_lf, o->nobject_files * sizeof(*obj_lf)); + driver_free(env, obj_names, o->inputs.nobject_files * sizeof(*obj_names)); + if (obj_lf) + driver_free(env, obj_lf, o->inputs.nobject_files * sizeof(*obj_lf)); /* The link session borrows the per-source builders (it frees only its own * pointer array), so the caller still owns and must release them. */ if (objs) { @@ -1792,8 +1509,9 @@ static int build_run_wasm_module(BuildOptions* o, KitCompiler* compiler, memset(&batch, 0, sizeof batch); batch.output_kind = KIT_CG_OUTPUT_RELOCATABLE; batch.interposition_policy = KIT_CG_INTERPOSITION_DEFAULT; - if (build_compile_all(o, compiler, ctx, &code2, diag, objs, source_obj_index, - source_order_keep, &batch, NULL, &nobjs) != 0) + if (build_compile_all(o, compiler, ctx, &code2, diag, objs, + source_obj_index, source_order_keep, &batch, NULL, + &nobjs) != 0) goto out; } if (nobjs != 1) { @@ -1821,8 +1539,7 @@ out: /* build-exe wasm: merge all sources into one .wasm with DCE/internalization. */ static int build_run_wasm_exe(BuildOptions* o, KitCompiler* compiler, - const KitContext* ctx, - const KitCodeOptions* code, + const KitContext* ctx, const KitCodeOptions* code, const KitDiagnosticOptions* diag) { DriverEnv* env = o->env; KitObjBuilder** objs = NULL; @@ -1853,8 +1570,8 @@ static int build_run_wasm_exe(BuildOptions* o, KitCompiler* compiler, batch.interposition_policy = KIT_CG_INTERPOSITION_NONE; batch.defer_lto_finish = 1; if (build_compile_all(o, compiler, ctx, &code2, diag, objs, - source_obj_index, source_order_keep, - &batch, &pending_lto, &nobjs) != 0) + source_obj_index, source_order_keep, &batch, + &pending_lto, &nobjs) != 0) goto out; } if (nobjs != 1) { @@ -1872,8 +1589,7 @@ static int build_run_wasm_exe(BuildOptions* o, KitCompiler* compiler, if (!entry_interned || kit_obj_builder_find_symbol(pending_lto.obj, entry_interned, &entry_sym) != KIT_OK) { - driver_errf(o->tool, - "build-exe: entry symbol '%s' not found in module", + driver_errf(o->tool, "build-exe: entry symbol '%s' not found in module", entry_name); goto out; } @@ -1881,8 +1597,8 @@ static int build_run_wasm_exe(BuildOptions* o, KitCompiler* compiler, memset(&batch2, 0, sizeof batch2); batch2.output_kind = KIT_CG_OUTPUT_EXECUTABLE; batch2.interposition_policy = KIT_CG_INTERPOSITION_NONE; - if (driver_compile_pending_lto_finish(&pending_lto, &batch2, - &csym, 1) != KIT_OK) { + if (driver_compile_pending_lto_finish(&pending_lto, &batch2, &csym, 1) != + KIT_OK) { driver_errf(o->tool, "build-exe: LTO finish failed"); goto out; } @@ -2042,8 +1758,8 @@ static int build_run_per_source(BuildOptions* o, KitCompiler* compiler, /* ===================================================================== */ static int build_validate(BuildOptions* o) { - uint32_t total_link = - o->nobject_files + o->narchives + o->ndsos + o->npending_libs; + uint32_t total_link = o->inputs.nobject_files + o->inputs.narchives + + o->inputs.ndsos + o->inputs.npending_libs; if (o->nsources == 0 && total_link == 0) { driver_errf(o->tool, "no input files"); @@ -2069,8 +1785,8 @@ static int build_validate(BuildOptions* o) { : driver_default_exe_name(o->target); } if (o->target.obj == KIT_OBJ_WASM) { - uint32_t total_link = - o->nobject_files + o->narchives + o->ndsos + o->npending_libs; + uint32_t total_link = o->inputs.nobject_files + o->inputs.narchives + + o->inputs.ndsos + o->inputs.npending_libs; if (total_link) { driver_errf(o->tool, "build-exe -target wasm32-none accepts only source files " @@ -2162,7 +1878,7 @@ static int build_validate(BuildOptions* o) { static int build_apply_env(BuildOptions* o) { const char* sde = driver_getenv("SOURCE_DATE_EPOCH"); - if (sde && build_parse_u64(sde, &o->epoch) != 0) { + if (sde && driver_parse_u64(sde, &o->epoch) != 0) { driver_errf(o->tool, "invalid SOURCE_DATE_EPOCH: %.*s", KIT_SLICE_ARG(kit_slice_cstr(sde))); return 1; @@ -2219,7 +1935,8 @@ static int build_main(int argc, char** argv, int kind, const char* tool) { } if (build_is_link_output(&o)) { - if (build_append_windows_lib_dirs(&o) != 0) { + if (driver_link_inputs_append_windows_lib_dirs(&o.inputs, &o.sysroot, + o.target) != 0) { rc = 1; goto done; } @@ -2229,7 +1946,8 @@ static int build_main(int argc, char** argv, int kind, const char* tool) { rc = 1; goto done; } - if (build_resolve_pending_libs(&o) != 0) { + if (driver_link_inputs_resolve_pending(&o.inputs, o.target, + o.static_link) != 0) { rc = 1; goto done; } @@ -2242,12 +1960,12 @@ static int build_main(int argc, char** argv, int kind, const char* tool) { rc = 1; goto done; } - insert_pos = o.nlink_items; + insert_pos = o.inputs.nlink_items; if (o.hosted.nfinal <= insert_pos) insert_pos -= o.hosted.nfinal; - build_insert_runtime_archive(&o, &rt, insert_pos); + driver_link_inputs_insert_runtime_archive(&o.inputs, &rt, insert_pos); driver_runtime_archive_fini(&env, &rt); } - } else if (o.npending_libs) { + } else if (o.inputs.npending_libs) { driver_errf(tool, "-l is only valid for build-exe"); rc = 1; goto done; @@ -2279,7 +1997,8 @@ static int build_main(int argc, char** argv, int kind, const char* tool) { if (o.target.obj == KIT_OBJ_WASM) rc = build_run_wasm_exe(&o, compiler, &ctx, &code, &diag); else - rc = build_run_link(&o, compiler, &ctx, &code, &diag, KIT_LINK_OUTPUT_EXE); + rc = + build_run_link(&o, compiler, &ctx, &code, &diag, KIT_LINK_OUTPUT_EXE); } else if (o.kind == BUILD_OUT_LIB) { rc = o.shared ? build_run_link(&o, compiler, &ctx, &code, &diag, KIT_LINK_OUTPUT_SHARED) diff --git a/driver/cmd/cc.c b/driver/cmd/cc.c @@ -15,6 +15,7 @@ #include "lib_resolve.h" #include "link_engine.h" #include "link_flags.h" +#include "link_inputs.h" #include "runtime.h" /* `kit cc` — C compiler driver. With -c produces a single object; @@ -71,45 +72,8 @@ typedef enum CcProbeKind { CC_PROBE_DUMPSPECS, } CcProbeKind; -typedef enum CcLinkItemKind { - CC_LINK_SOURCE_FILE, - CC_LINK_SOURCE_MEMORY, - CC_LINK_OBJECT, - CC_LINK_ARCHIVE, - CC_LINK_DSO, - CC_LINK_LIB, -} CcLinkItemKind; - -typedef struct CcLinkItem { - uint8_t kind; /* CcLinkItemKind */ - uint8_t pad[3]; - uint32_t index; -} CcLinkItem; - -typedef struct CcArchiveInput { - const char* path; - int owned; - size_t owned_size; - uint8_t whole_archive; - uint8_t link_mode; - uint8_t group_id; - uint8_t pad; -} CcArchiveInput; - -typedef struct CcDsoInput { - const char* path; - int owned; - size_t owned_size; -} CcDsoInput; - -typedef struct CcPendingLib { - const char* name; - uint8_t whole_archive; - uint8_t link_mode; - uint8_t group_id; - uint8_t resolved_kind; /* CcLinkItemKind: ARCHIVE or DSO */ - uint32_t resolved_index; -} CcPendingLib; +/* Link-input model (link items + object/archive/dso/lib arrays) is shared with + * the build-* drivers; see driver/lib/link_inputs.h. */ typedef struct CcOptions { DriverEnv* env; @@ -164,28 +128,9 @@ typedef struct CcOptions { uint32_t nsource_memory; uint8_t* stdin_buf; /* owning storage for the one stdin */ size_t stdin_size; - const char** object_files; /* .o/.obj paths */ - uint32_t nobject_files; - CcArchiveInput* archives; /* .a paths + resolved -l names */ - uint32_t narchives; - CcDsoInput* dsos; - uint32_t ndsos; - /* -L search paths (argv-borrowed; last slot may be owned, see - * owned_sysroot_lib_dir). */ - const char** lib_search_paths; - uint32_t nlib_search_paths; - /* Owned `<sysroot>/lib` slot appended for Windows targets when a - * sysroot is in effect (cmdline or KIT_SYSROOT). */ - char* owned_sysroot_lib_dir; - size_t owned_sysroot_lib_dir_size; - /* Pending -l names (resolved at end-of-parse). */ - CcPendingLib* pending_libs; - uint32_t npending_libs; - CcLinkItem* link_items; - uint32_t nlink_items; - uint8_t cur_whole_archive; - uint8_t cur_link_mode; - uint8_t cur_group_id; + /* Shared link-input model: object/archive/dso/lib arrays, the ordered link + * item list, -L search paths, and the owned `<sysroot>/lib` Windows slot. */ + DriverLinkInputSet inputs; uint8_t next_group_id; /* -M family */ @@ -278,15 +223,6 @@ static int cc_alloc_arrays(CcOptions* o, int argc) { driver_alloc_zeroed(o->env, bound * sizeof(*o->source_langs)); o->source_memory = driver_alloc_zeroed(o->env, bound * sizeof(*o->source_memory)); - o->object_files = - driver_alloc_zeroed(o->env, bound * sizeof(*o->object_files)); - o->archives = driver_alloc_zeroed(o->env, bound * sizeof(*o->archives)); - o->dsos = driver_alloc_zeroed(o->env, bound * sizeof(*o->dsos)); - o->lib_search_paths = - driver_alloc_zeroed(o->env, bound * sizeof(*o->lib_search_paths)); - o->pending_libs = - driver_alloc_zeroed(o->env, bound * sizeof(*o->pending_libs)); - o->link_items = driver_alloc_zeroed(o->env, bound * sizeof(*o->link_items)); o->dep_targets = driver_alloc_zeroed(o->env, bound * sizeof(*o->dep_targets)); o->path_map = driver_alloc_zeroed(o->env, bound * sizeof(*o->path_map)); o->owned_path_map_olds = @@ -294,13 +230,13 @@ static int cc_alloc_arrays(CcOptions* o, int argc) { o->owned_path_map_old_sizes = driver_alloc_zeroed(o->env, bound * sizeof(*o->owned_path_map_old_sizes)); if (!o->source_files || !o->source_langs || !o->source_memory || - !o->object_files || !o->archives || !o->dsos || !o->lib_search_paths || - !o->pending_libs || !o->link_items || !o->dep_targets || !o->path_map || - !o->owned_path_map_olds || !o->owned_path_map_old_sizes) { + !o->dep_targets || !o->path_map || !o->owned_path_map_olds || + !o->owned_path_map_old_sizes) { driver_errf(CC_TOOL, "out of memory"); return 1; } - o->cur_link_mode = KIT_LM_DEFAULT; + if (driver_link_inputs_init(&o->inputs, o->env, CC_TOOL, bound) != 0) + return 1; if (driver_link_flags_init(&o->link, o->env, CC_TOOL, (uint32_t)bound) != 0 || driver_cflags_init(&o->cf, o->env, (int)(bound + DRIVER_HOSTED_MAX_DEFINES + @@ -315,17 +251,6 @@ static int cc_alloc_arrays(CcOptions* o, int argc) { static void cc_options_release(CcOptions* o) { uint32_t i; size_t bound = o->argv_bound; - for (i = 0; i < o->narchives; ++i) { - if (o->archives[i].owned) { - driver_free(o->env, (void*)o->archives[i].path, - o->archives[i].owned_size); - } - } - for (i = 0; i < o->ndsos; ++i) { - if (o->dsos[i].owned) { - driver_free(o->env, (void*)o->dsos[i].path, o->dsos[i].owned_size); - } - } for (i = 0; i < o->npath_map; ++i) { if (o->owned_path_map_olds[i]) { driver_free(o->env, o->owned_path_map_olds[i], @@ -335,9 +260,7 @@ static void cc_options_release(CcOptions* o) { if (o->stdin_buf) driver_free(o->env, o->stdin_buf, o->stdin_size); if (o->owned_output_path) driver_free(o->env, o->owned_output_path, o->owned_output_path_size); - if (o->owned_sysroot_lib_dir) - driver_free(o->env, o->owned_sysroot_lib_dir, - o->owned_sysroot_lib_dir_size); + driver_link_inputs_fini(&o->inputs); driver_hosted_plan_fini(o->env, &o->hosted); driver_link_flags_fini(&o->link); driver_target_features_fini(&o->target_features, o->env); @@ -345,13 +268,6 @@ static void cc_options_release(CcOptions* o) { driver_free(o->env, o->source_files, bound * sizeof(*o->source_files)); driver_free(o->env, o->source_langs, bound * sizeof(*o->source_langs)); driver_free(o->env, o->source_memory, bound * sizeof(*o->source_memory)); - driver_free(o->env, o->object_files, bound * sizeof(*o->object_files)); - driver_free(o->env, o->archives, bound * sizeof(*o->archives)); - driver_free(o->env, o->dsos, bound * sizeof(*o->dsos)); - driver_free(o->env, o->lib_search_paths, - bound * sizeof(*o->lib_search_paths)); - driver_free(o->env, o->pending_libs, bound * sizeof(*o->pending_libs)); - driver_free(o->env, o->link_items, bound * sizeof(*o->link_items)); driver_free(o->env, o->dep_targets, bound * sizeof(*o->dep_targets)); driver_free(o->env, o->path_map, bound * sizeof(*o->path_map)); driver_free(o->env, o->owned_path_map_olds, @@ -368,99 +284,6 @@ static int cc_apply_hosted_profile(CcOptions* o); * helper excludes it. */ static int cc_is_c_source(const char* s) { return driver_path_is_source(s); } -static int cc_is_dso_input(const char* s) { - return driver_has_suffix(s, ".so") || driver_has_suffix(s, ".dylib") || - driver_has_suffix(s, ".tbd"); -} - -static void cc_push_link_item(CcOptions* o, uint8_t kind, uint32_t index) { - CcLinkItem* it = &o->link_items[o->nlink_items++]; - it->kind = kind; - it->index = index; -} - -static void cc_insert_link_item(CcOptions* o, uint32_t pos, uint8_t kind, - uint32_t index) { - uint32_t i; - if (pos > o->nlink_items) pos = o->nlink_items; - for (i = o->nlink_items; i > pos; --i) { - o->link_items[i] = o->link_items[i - 1u]; - } - o->link_items[pos].kind = kind; - o->link_items[pos].index = index; - o->nlink_items++; -} - -static int cc_append_hosted_input(CcOptions* o, const DriverHostedInput* in, - uint32_t insert_pos, int insert) { - uint32_t index; - uint8_t kind; - switch ((DriverHostedInputKind)in->kind) { - case DRIVER_HOSTED_INPUT_OBJECT: - index = o->nobject_files++; - o->object_files[index] = in->path; - kind = CC_LINK_OBJECT; - break; - case DRIVER_HOSTED_INPUT_ARCHIVE: { - CcArchiveInput* ar = &o->archives[o->narchives++]; - ar->path = in->path; - ar->whole_archive = 0; - ar->link_mode = KIT_LM_DEFAULT; - ar->group_id = 0; - index = o->narchives - 1u; - kind = CC_LINK_ARCHIVE; - break; - } - case DRIVER_HOSTED_INPUT_DSO: { - CcDsoInput* d = &o->dsos[o->ndsos++]; - d->path = in->path; - index = o->ndsos - 1u; - kind = CC_LINK_DSO; - break; - } - default: - driver_errf(CC_TOOL, "internal error: unknown hosted input kind"); - return 1; - } - if (insert) - cc_insert_link_item(o, insert_pos, kind, index); - else - cc_push_link_item(o, kind, index); - return 0; -} - -static void cc_insert_runtime_archive(CcOptions* o, DriverRuntimeArchive* rt, - uint32_t insert_pos) { - CcArchiveInput* ar = &o->archives[o->narchives++]; - ar->path = rt->path; - ar->owned = 1; - ar->owned_size = rt->path_size; - ar->whole_archive = rt->whole_archive; - ar->link_mode = rt->link_mode; - ar->group_id = rt->group_id; - rt->path = NULL; - rt->path_size = 0; - cc_insert_link_item(o, insert_pos, CC_LINK_ARCHIVE, o->narchives - 1u); -} - -static int cc_parse_u64(const char* s, uint64_t* out) { - uint64_t v = 0; - int any = 0; - if (!s) return 1; - while (*s) { - unsigned d; - if (*s < '0' || *s > '9') return 1; - d = (unsigned)(*s - '0'); - if (v > (UINT64_MAX - d) / 10u) return 1; - v = v * 10u + d; - any = 1; - s++; - } - if (!any) return 1; - *out = v; - return 0; -} - static int cc_record_path_map(CcOptions* o, const char* arg) { const char* eq = driver_strchr(arg, '='); KitPathPrefixMap* m = &o->path_map[o->npath_map]; @@ -487,32 +310,6 @@ static int cc_record_path_map(CcOptions* o, const char* arg) { return 0; } -static int cc_record_mcmodel(CcOptions* o, const char* val) { - if (driver_streq(val, "small")) { - o->target.code_model = KIT_CM_SMALL; - return 0; - } - if (driver_streq(val, "medium")) { - o->target.code_model = KIT_CM_MEDIUM; - return 0; - } - if (driver_streq(val, "large")) { - o->target.code_model = KIT_CM_LARGE; - return 0; - } - if (driver_streq(val, "medlow")) { - o->target.code_model = KIT_CM_SMALL; - return 0; - } - if (driver_streq(val, "medany")) { - o->target.code_model = KIT_CM_MEDIUM; - return 0; - } - driver_errf(CC_TOOL, "unknown -mcmodel value: %.*s", - KIT_SLICE_ARG(kit_slice_cstr(val))); - return 1; -} - static int cc_set_probe(CcOptions* o, int kind, const char* arg) { if (o->probe_kind != CC_PROBE_NONE) { driver_errf(CC_TOOL, "only one compiler-information probe is supported"); @@ -573,8 +370,8 @@ static int cc_run_probe(CcOptions* o) { if (have_dirs) for (i = 0; i < dirs.nlibdirs; ++i) cc_print_path_elem(dirs.libdirs[i], &first); - for (i = 0; i < o->nlib_search_paths; ++i) - cc_print_path_elem(o->lib_search_paths[i], &first); + for (i = 0; i < o->inputs.nlib_search_paths; ++i) + cc_print_path_elem(o->inputs.lib_search_paths[i], &first); if (have_rt) cc_print_path_elem(rt.rt_root, &first); driver_printf("\n"); /* includes: user -I/-isystem, then the hosted system headers, then the @@ -679,7 +476,8 @@ static int cc_record_stdin(CcOptions* o, int forced_lang) { in->bytes.data = o->stdin_buf; in->bytes.len = o->stdin_size; in->lang = forced_lang >= 0 ? (KitLanguage)forced_lang : KIT_LANG_C; - cc_push_link_item(o, CC_LINK_SOURCE_MEMORY, o->nsource_memory - 1u); + driver_link_inputs_push(&o->inputs, DRIVER_LINK_SOURCE_MEMORY, + o->nsource_memory - 1u); return 0; } @@ -701,27 +499,30 @@ static int cc_classify_positional(CcOptions* o, const char* a, o->source_langs[o->nsource_files] = forced_lang >= 0 ? (KitLanguage)forced_lang : CC_LANG_AUTO; o->source_files[o->nsource_files++] = a; - cc_push_link_item(o, CC_LINK_SOURCE_FILE, o->nsource_files - 1u); + driver_link_inputs_push(&o->inputs, DRIVER_LINK_SOURCE, + o->nsource_files - 1u); return 0; } if (driver_has_suffix(a, ".o") || driver_has_suffix(a, ".obj")) { - o->object_files[o->nobject_files++] = a; - cc_push_link_item(o, CC_LINK_OBJECT, o->nobject_files - 1u); + o->inputs.object_files[o->inputs.nobject_files++] = a; + driver_link_inputs_push(&o->inputs, DRIVER_LINK_OBJECT, + o->inputs.nobject_files - 1u); return 0; } if (driver_has_suffix(a, ".a")) { - CcArchiveInput* ar = &o->archives[o->narchives++]; + DriverArchiveInput* ar = &o->inputs.archives[o->inputs.narchives++]; ar->path = a; - ar->whole_archive = o->cur_whole_archive; - ar->link_mode = o->cur_link_mode; - ar->group_id = o->cur_group_id; - cc_push_link_item(o, CC_LINK_ARCHIVE, o->narchives - 1u); + ar->whole_archive = o->inputs.cur_whole_archive; + ar->link_mode = o->inputs.cur_link_mode; + ar->group_id = o->inputs.cur_group_id; + driver_link_inputs_push(&o->inputs, DRIVER_LINK_ARCHIVE, + o->inputs.narchives - 1u); return 0; } - if (cc_is_dso_input(a)) { - CcDsoInput* d = &o->dsos[o->ndsos++]; + if (driver_is_dso_path(a)) { + DriverDsoInput* d = &o->inputs.dsos[o->inputs.ndsos++]; d->path = a; - cc_push_link_item(o, CC_LINK_DSO, o->ndsos - 1u); + driver_link_inputs_push(&o->inputs, DRIVER_LINK_DSO, o->inputs.ndsos - 1u); return 0; } driver_errf(CC_TOOL, "input does not have a recognized suffix: %.*s", @@ -729,52 +530,9 @@ static int cc_classify_positional(CcOptions* o, const char* a, return 1; } -static int cc_resolve_pending_libs(CcOptions* o) { - uint32_t i; - for (i = 0; i < o->npending_libs; ++i) { - CcPendingLib* pl = &o->pending_libs[i]; - char* p; - size_t sz; - LibResolveKind kind; - LibResolveMode mode = (o->static_link || pl->link_mode == KIT_LM_STATIC) - ? LIB_RESOLVE_STATIC_ONLY - : LIB_RESOLVE_DYNAMIC_PREFER; - LibResolveOS resolve_os = (o->target.os == KIT_OS_WINDOWS) - ? LIB_RESOLVE_OS_WINDOWS - : LIB_RESOLVE_OS_POSIX; - if (driver_lib_resolve_for_os(o->env, pl->name, mode, resolve_os, - o->lib_search_paths, o->nlib_search_paths, &p, - &sz, &kind) != 0) { - driver_errf(CC_TOOL, "library not found: -l%.*s", - KIT_SLICE_ARG(kit_slice_cstr(pl->name))); - return 1; - } - if (kind == LIB_RESOLVE_KIND_SHARED || kind == LIB_RESOLVE_KIND_TBD) { - CcDsoInput* d = &o->dsos[o->ndsos++]; - d->path = p; - d->owned = 1; - d->owned_size = sz; - pl->resolved_kind = CC_LINK_DSO; - pl->resolved_index = o->ndsos - 1u; - } else { - CcArchiveInput* ar = &o->archives[o->narchives++]; - ar->path = p; - ar->owned = 1; - ar->owned_size = sz; - ar->whole_archive = pl->whole_archive; - ar->link_mode = pl->link_mode; - ar->group_id = pl->group_id; - pl->resolved_kind = CC_LINK_ARCHIVE; - pl->resolved_index = o->narchives - 1u; - } - } - return 0; -} - static int cc_apply_hosted_profile(CcOptions* o) { - DriverHostedRequest req; - uint32_t i; - uint32_t insert_pos = 0; + /* A link action (not -c/-E/-M/-MM) gets crt files + interpreter; the include + * + define + lib-search-dir parts apply regardless. */ int link_action = !o->compile_only && !o->preprocess_only && o->dep_mode != CC_DEP_M && o->dep_mode != CC_DEP_MM; if (!o->wants_hosted_libc || o->shared) return 0; @@ -783,51 +541,14 @@ static int cc_apply_hosted_profile(CcOptions* o) { "-lc hosted expansion is disabled by -nostdlib/-nodefaultlibs"); return 1; } - { - DriverHostedRequest z = {0}; - req = z; - } - req.env = o->env; - req.tool = CC_TOOL; - req.target = o->target; - req.sysroot = o->sysroot; - req.static_link = o->static_link; - req.link_inputs = link_action; - if (driver_hosted_resolve(&req, &o->hosted) != 0) return 1; - for (i = 0; i < o->hosted.nsystem_includes; ++i) { - o->cf.system_include_dirs[o->cf.nsystem_include_dirs++] = - o->hosted.system_includes[i]; - } - for (i = 0; i < o->hosted.ndefines; ++i) { - o->cf.defines[o->cf.ndefines++] = o->hosted.defines[i]; - } - /* Add hosted lib search dirs so user -l flags (-lm, -lpthread, etc.) can be - * resolved. The strings are owned by o->hosted and outlive lib_search_paths. - * Insert before any user -L dirs so sysroot libs take precedence. */ - for (i = 0; i < o->hosted.nlib_search_dirs; ++i) - o->lib_search_paths[o->nlib_search_paths++] = o->hosted.lib_search_dirs[i]; - if (!link_action) return 0; - for (i = 0; i < o->hosted.nbefore; ++i) { - if (o->no_startfiles) break; - if (cc_append_hosted_input(o, &o->hosted.before[i], insert_pos, 1) != 0) - return 1; - insert_pos++; - } - for (i = 0; i < o->hosted.nafter; ++i) { - if (cc_append_hosted_input(o, &o->hosted.after[i], 0, 0) != 0) return 1; - } - for (i = 0; i < o->hosted.nfinal; ++i) { - if (o->no_startfiles) break; - if (cc_append_hosted_input(o, &o->hosted.final[i], 0, 0) != 0) return 1; - } - if (!o->link.interp_path && o->hosted.interp_path) - o->link.interp_path = o->hosted.interp_path; - return 0; + return driver_link_inputs_apply_hosted( + &o->inputs, &o->hosted, &o->cf, &o->link, o->target, o->sysroot, + o->static_link, o->no_startfiles, link_action); } static int cc_apply_env(CcOptions* o) { const char* sde = driver_getenv("SOURCE_DATE_EPOCH"); - if (sde && cc_parse_u64(sde, &o->epoch) != 0) { + if (sde && driver_parse_u64(sde, &o->epoch) != 0) { driver_errf(CC_TOOL, "invalid SOURCE_DATE_EPOCH: %.*s", KIT_SLICE_ARG(kit_slice_cstr(sde))); return 1; @@ -835,58 +556,6 @@ static int cc_apply_env(CcOptions* o) { return 0; } -/* Append a default `<sysroot>/lib` to the library search path for - * Windows targets. The llvm-mingw UCRT sysroot ships import archives - * such as libkernel32.a, libucrt.a, and the UCRT API-set archives - * under <sysroot>/lib; the user-supplied -L list is searched first, - * then this appended default. Sysroot resolution order: - * 1. -isysroot / --sysroot on the command line (already in - * o->sysroot at this point); - * 2. KIT_SYSROOT env var (e.g. .../x86_64-w64-mingw32). - * - * No-op for non-Windows targets and for Windows when neither source - * provides a sysroot — keeps existing tests untouched. The appended - * path aliases the sysroot string for its lifetime; o->sysroot is - * either argv-borrowed or env-borrowed, both stable across the - * driver run, so the lib_search_paths slot remains valid. */ -static int cc_append_windows_lib_dirs(CcOptions* o) { - const char* sysroot = o->sysroot; - char* joined = NULL; - size_t srlen; - size_t need_slash; - size_t bytes; - size_t off = 0; - if (!driver_target_needs_sysroot_libdir(o->target)) return 0; - if (!sysroot || !sysroot[0]) { - sysroot = driver_getenv("KIT_SYSROOT"); - if (!sysroot || !sysroot[0]) return 0; - o->sysroot = sysroot; - } - srlen = driver_strlen(sysroot); - need_slash = (srlen > 0 && sysroot[srlen - 1] != '/') ? 1u : 0u; - /* "<sysroot>" + "/"? + "lib" + NUL */ - bytes = srlen + need_slash + 3u + 1u; - joined = driver_alloc(o->env, bytes); - if (!joined) { - driver_errf(CC_TOOL, "out of memory"); - return 1; - } - driver_memcpy(joined + off, sysroot, srlen); - off += srlen; - if (need_slash) joined[off++] = '/'; - driver_memcpy(joined + off, "lib", 3); - off += 3; - joined[off] = '\0'; - if (o->owned_sysroot_lib_dir) { - driver_free(o->env, o->owned_sysroot_lib_dir, - o->owned_sysroot_lib_dir_size); - } - o->owned_sysroot_lib_dir = joined; - o->owned_sysroot_lib_dir_size = bytes; - o->lib_search_paths[o->nlib_search_paths++] = joined; - return 0; -} - static int cc_has_link_action(const CcOptions* o) { return !o->compile_only && !o->preprocess_only && o->dep_mode != CC_DEP_M && o->dep_mode != CC_DEP_MM; @@ -1012,7 +681,7 @@ static int cc_parse(int argc, char** argv, CcOptions* o) { } if (driver_strneq(a, "-fmax-errors=", 13)) { uint64_t v; - if (cc_parse_u64(a + 13, &v) != 0 || v > 0xFFFFFFFFu) { + if (driver_parse_u64(a + 13, &v) != 0 || v > 0xFFFFFFFFu) { driver_errf(CC_TOOL, "-fmax-errors= requires a non-negative integer"); return 1; } @@ -1183,7 +852,7 @@ static int cc_parse(int argc, char** argv, CcOptions* o) { if (driver_streq(a, "-static")) { o->target.pic = KIT_PIC_NONE; o->static_link = 1; - o->cur_link_mode = KIT_LM_STATIC; + o->inputs.cur_link_mode = KIT_LM_STATIC; continue; } if (driver_streq(a, "-pie")) { @@ -1208,31 +877,31 @@ static int cc_parse(int argc, char** argv, CcOptions* o) { continue; } if (driver_streq(a, "-Bstatic")) { - o->cur_link_mode = KIT_LM_STATIC; + o->inputs.cur_link_mode = KIT_LM_STATIC; continue; } if (driver_streq(a, "-Bdynamic")) { - o->cur_link_mode = KIT_LM_DYNAMIC; + o->inputs.cur_link_mode = KIT_LM_DYNAMIC; continue; } if (driver_streq(a, "--as-needed")) { - o->cur_link_mode = KIT_LM_AS_NEEDED; + o->inputs.cur_link_mode = KIT_LM_AS_NEEDED; continue; } if (driver_streq(a, "--no-as-needed")) { - o->cur_link_mode = KIT_LM_DYNAMIC; + o->inputs.cur_link_mode = KIT_LM_DYNAMIC; continue; } if (driver_streq(a, "--whole-archive")) { - o->cur_whole_archive = 1; + o->inputs.cur_whole_archive = 1; continue; } if (driver_streq(a, "--no-whole-archive")) { - o->cur_whole_archive = 0; + o->inputs.cur_whole_archive = 0; continue; } if (driver_streq(a, "--start-group")) { - if (o->cur_group_id != 0) { + if (o->inputs.cur_group_id != 0) { driver_errf(CC_TOOL, "nested --start-group is not supported"); return 1; } @@ -1240,15 +909,15 @@ static int cc_parse(int argc, char** argv, CcOptions* o) { driver_errf(CC_TOOL, "too many --start-group occurrences"); return 1; } - o->cur_group_id = ++o->next_group_id; + o->inputs.cur_group_id = ++o->next_group_id; continue; } if (driver_streq(a, "--end-group")) { - if (o->cur_group_id == 0) { + if (o->inputs.cur_group_id == 0) { driver_errf(CC_TOOL, "--end-group without --start-group"); return 1; } - o->cur_group_id = 0; + o->inputs.cur_group_id = 0; continue; } @@ -1271,7 +940,7 @@ static int cc_parse(int argc, char** argv, CcOptions* o) { } if (driver_strneq(a, "-mcmodel=", 9)) { - if (cc_record_mcmodel(o, a + 9) != 0) return 1; + if (driver_record_mcmodel(&o->target, CC_TOOL, a + 9) != 0) return 1; continue; } { @@ -1400,7 +1069,7 @@ static int cc_parse(int argc, char** argv, CcOptions* o) { driver_errf(CC_TOOL, "-L requires an argument"); return 1; } - o->lib_search_paths[o->nlib_search_paths++] = dir; + o->inputs.lib_search_paths[o->inputs.nlib_search_paths++] = dir; continue; } if (driver_strneq(a, "-l", 2)) { @@ -1414,12 +1083,14 @@ static int cc_parse(int argc, char** argv, CcOptions* o) { continue; } { - CcPendingLib* pl = &o->pending_libs[o->npending_libs++]; + DriverPendingLib* pl = + &o->inputs.pending_libs[o->inputs.npending_libs++]; pl->name = name; - pl->whole_archive = o->cur_whole_archive; - pl->link_mode = o->cur_link_mode; - pl->group_id = o->cur_group_id; - cc_push_link_item(o, CC_LINK_LIB, o->npending_libs - 1u); + pl->whole_archive = o->inputs.cur_whole_archive; + pl->link_mode = o->inputs.cur_link_mode; + pl->group_id = o->inputs.cur_group_id; + driver_link_inputs_push(&o->inputs, DRIVER_LINK_LIB, + o->inputs.npending_libs - 1u); } continue; } @@ -1484,12 +1155,14 @@ static int cc_parse(int argc, char** argv, CcOptions* o) { if (o->probe_kind != CC_PROBE_NONE) return 0; if (cc_apply_env(o) != 0) return 1; - if (cc_append_windows_lib_dirs(o) != 0) return 1; + if (driver_link_inputs_append_windows_lib_dirs(&o->inputs, &o->sysroot, + o->target) != 0) + return 1; { uint32_t total_sources = o->nsource_files + o->nsource_memory; - uint32_t total_link = - o->nobject_files + o->narchives + o->ndsos + o->npending_libs; + uint32_t total_link = o->inputs.nobject_files + o->inputs.narchives + + o->inputs.ndsos + o->inputs.npending_libs; if (total_sources == 0 && total_link == 0) { driver_errf(CC_TOOL, "no input files"); @@ -1546,7 +1219,7 @@ static int cc_parse(int argc, char** argv, CcOptions* o) { driver_errf(CC_TOOL, "-Wl,-soname requires -shared"); return 1; } - if (o->cur_group_id != 0) { + if (o->inputs.cur_group_id != 0) { driver_errf(CC_TOOL, "missing --end-group"); return 1; } @@ -1611,7 +1284,9 @@ 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; - if (!o->syntax_only && cc_resolve_pending_libs(o) != 0) return 1; + if (!o->syntax_only && driver_link_inputs_resolve_pending( + &o->inputs, o->target, o->static_link) != 0) + return 1; return 0; } @@ -2394,34 +2069,37 @@ static int cc_run_link_exe(DriverEnv* env, const CcOptions* o, goto out; } } - if (o->nobject_files) { - obj_lf = driver_alloc_zeroed(env, o->nobject_files * sizeof(*obj_lf)); - obj_in = driver_alloc_zeroed(env, o->nobject_files * sizeof(*obj_in)); - obj_names = driver_alloc_zeroed(env, o->nobject_files * sizeof(*obj_names)); + if (o->inputs.nobject_files) { + obj_lf = + driver_alloc_zeroed(env, o->inputs.nobject_files * sizeof(*obj_lf)); + obj_in = + driver_alloc_zeroed(env, o->inputs.nobject_files * sizeof(*obj_in)); + obj_names = + driver_alloc_zeroed(env, o->inputs.nobject_files * sizeof(*obj_names)); if (!obj_lf || !obj_in || !obj_names) { driver_errf(CC_TOOL, "out of memory"); goto out; } } - if (o->narchives) { - arch_lf = driver_alloc_zeroed(env, o->narchives * sizeof(*arch_lf)); - arch_in = driver_alloc_zeroed(env, o->narchives * sizeof(*arch_in)); + if (o->inputs.narchives) { + arch_lf = driver_alloc_zeroed(env, o->inputs.narchives * sizeof(*arch_lf)); + arch_in = driver_alloc_zeroed(env, o->inputs.narchives * sizeof(*arch_in)); if (!arch_lf || !arch_in) { driver_errf(CC_TOOL, "out of memory"); goto out; } } - if (o->ndsos) { - dso_lf = driver_alloc_zeroed(env, o->ndsos * sizeof(*dso_lf)); - dso_in = driver_alloc_zeroed(env, o->ndsos * sizeof(*dso_in)); - dso_names = driver_alloc_zeroed(env, o->ndsos * sizeof(*dso_names)); + if (o->inputs.ndsos) { + dso_lf = driver_alloc_zeroed(env, o->inputs.ndsos * sizeof(*dso_lf)); + dso_in = driver_alloc_zeroed(env, o->inputs.ndsos * sizeof(*dso_in)); + dso_names = driver_alloc_zeroed(env, o->inputs.ndsos * sizeof(*dso_names)); if (!dso_lf || !dso_in || !dso_names) { driver_errf(CC_TOOL, "out of memory"); goto out; } } - if (o->nlink_items) { - order = driver_alloc_zeroed(env, o->nlink_items * sizeof(*order)); + if (o->inputs.nlink_items) { + order = driver_alloc_zeroed(env, o->inputs.nlink_items * sizeof(*order)); if (!order) { driver_errf(CC_TOOL, "out of memory"); goto out; @@ -2434,25 +2112,25 @@ static int cc_run_link_exe(DriverEnv* env, const CcOptions* o, goto out; } - for (i = 0; i < o->nobject_files; ++i) { - if (driver_load_bytes(io, CC_TOOL, o->object_files[i], &obj_lf[i], + for (i = 0; i < o->inputs.nobject_files; ++i) { + if (driver_load_bytes(io, CC_TOOL, o->inputs.object_files[i], &obj_lf[i], &obj_in[i]) != 0) goto out; - obj_names[i] = kit_slice_cstr(o->object_files[i]); + obj_names[i] = kit_slice_cstr(o->inputs.object_files[i]); } - for (i = 0; i < o->narchives; ++i) { - if (driver_load_bytes(io, CC_TOOL, o->archives[i].path, &arch_lf[i], + for (i = 0; i < o->inputs.narchives; ++i) { + if (driver_load_bytes(io, CC_TOOL, o->inputs.archives[i].path, &arch_lf[i], &arch_in[i].bytes) != 0) goto out; - arch_in[i].link_mode = o->archives[i].link_mode; - arch_in[i].whole_archive = o->archives[i].whole_archive; - arch_in[i].group_id = o->archives[i].group_id; + arch_in[i].link_mode = o->inputs.archives[i].link_mode; + arch_in[i].whole_archive = o->inputs.archives[i].whole_archive; + arch_in[i].group_id = o->inputs.archives[i].group_id; } - for (i = 0; i < o->ndsos; ++i) { - if (driver_load_bytes(io, CC_TOOL, o->dsos[i].path, &dso_lf[i], + for (i = 0; i < o->inputs.ndsos; ++i) { + if (driver_load_bytes(io, CC_TOOL, o->inputs.dsos[i].path, &dso_lf[i], &dso_in[i]) != 0) goto out; - dso_names[i] = kit_slice_cstr(o->dsos[i].path); + dso_names[i] = kit_slice_cstr(o->inputs.dsos[i].path); } if (o->link.linker_script) { @@ -2536,23 +2214,23 @@ static int cc_run_link_exe(DriverEnv* env, const CcOptions* o, goto out; /* Translate the command-line link order into the engine's public - * KitLinkInputOrder list. The dead-simple fallback for o->nlink_items == 0 - * never fires (a link action always has at least one input), so every add - * flows through the ordered path. */ + * KitLinkInputOrder list. The dead-simple fallback for + * o->inputs.nlink_items == 0 never fires (a link action always has at least + * one input), so every add flows through the ordered path. */ { uint32_t oi; DriverLinkInputs li; - for (oi = 0; oi < o->nlink_items; ++oi) { - const CcLinkItem* item = &o->link_items[oi]; + for (oi = 0; oi < o->inputs.nlink_items; ++oi) { + const DriverLinkItem* item = &o->inputs.link_items[oi]; KitLinkInputOrder* ord; - switch ((CcLinkItemKind)item->kind) { - case CC_LINK_SOURCE_FILE: + switch ((DriverLinkKind)item->kind) { + case DRIVER_LINK_SOURCE: if (!source_order_keep[item->index]) continue; ord = &order[norder++]; ord->kind = KIT_LINK_INPUT_OBJ; ord->index = source_obj_index[item->index]; break; - case CC_LINK_SOURCE_MEMORY: { + case DRIVER_LINK_SOURCE_MEMORY: { uint32_t si = o->nsource_files + item->index; if (!source_order_keep[si]) continue; ord = &order[norder++]; @@ -2560,25 +2238,25 @@ static int cc_run_link_exe(DriverEnv* env, const CcOptions* o, ord->index = source_obj_index[si]; break; } - case CC_LINK_OBJECT: + case DRIVER_LINK_OBJECT: ord = &order[norder++]; ord->kind = KIT_LINK_INPUT_OBJ_BYTES; ord->index = item->index; break; - case CC_LINK_ARCHIVE: + case DRIVER_LINK_ARCHIVE: ord = &order[norder++]; ord->kind = KIT_LINK_INPUT_ARCHIVE; ord->index = item->index; break; - case CC_LINK_DSO: + case DRIVER_LINK_DSO: ord = &order[norder++]; ord->kind = KIT_LINK_INPUT_DSO; ord->index = item->index; break; - case CC_LINK_LIB: { - const CcPendingLib* pl = &o->pending_libs[item->index]; + case DRIVER_LINK_LIB: { + const DriverPendingLib* pl = &o->inputs.pending_libs[item->index]; ord = &order[norder++]; - if (pl->resolved_kind == CC_LINK_DSO) { + if (pl->resolved_kind == DRIVER_LINK_DSO) { ord->kind = KIT_LINK_INPUT_DSO; ord->index = pl->resolved_index; } else { @@ -2594,12 +2272,12 @@ static int cc_run_link_exe(DriverEnv* env, const CcOptions* o, li.nobjs = nobjs; li.obj_names = obj_names; li.obj_bytes = obj_in; - li.nobj_bytes = o->nobject_files; + li.nobj_bytes = o->inputs.nobject_files; li.archives = arch_in; - li.narchives = o->narchives; + li.narchives = o->inputs.narchives; li.dso_names = dso_names; li.dso_bytes = dso_in; - li.ndsos = o->ndsos; + li.ndsos = o->inputs.ndsos; li.order = order; li.norder = norder; st = driver_link_engine_emit_with_lto(compiler, &lopts, &li, &pending_lto, @@ -2624,27 +2302,34 @@ out: kit_target_free(target); driver_release_bytes(io, &script_lf); if (arch_lf) { - for (i = 0; i < o->narchives; ++i) driver_release_bytes(io, &arch_lf[i]); + for (i = 0; i < o->inputs.narchives; ++i) + driver_release_bytes(io, &arch_lf[i]); } if (dso_lf) { - for (i = 0; i < o->ndsos; ++i) driver_release_bytes(io, &dso_lf[i]); + for (i = 0; i < o->inputs.ndsos; ++i) driver_release_bytes(io, &dso_lf[i]); } if (obj_lf) { - for (i = 0; i < o->nobject_files; ++i) driver_release_bytes(io, &obj_lf[i]); + for (i = 0; i < o->inputs.nobject_files; ++i) + driver_release_bytes(io, &obj_lf[i]); } if (src_lf) { for (i = 0; i < o->nsource_files; ++i) driver_release_bytes(io, &src_lf[i]); } - if (arch_in) driver_free(env, arch_in, o->narchives * sizeof(*arch_in)); - if (arch_lf) driver_free(env, arch_lf, o->narchives * sizeof(*arch_lf)); - if (dso_in) driver_free(env, dso_in, o->ndsos * sizeof(*dso_in)); - if (dso_names) driver_free(env, dso_names, o->ndsos * sizeof(*dso_names)); - if (dso_lf) driver_free(env, dso_lf, o->ndsos * sizeof(*dso_lf)); - if (order) driver_free(env, order, o->nlink_items * sizeof(*order)); - if (obj_in) driver_free(env, obj_in, o->nobject_files * sizeof(*obj_in)); + if (arch_in) + driver_free(env, arch_in, o->inputs.narchives * sizeof(*arch_in)); + if (arch_lf) + driver_free(env, arch_lf, o->inputs.narchives * sizeof(*arch_lf)); + if (dso_in) driver_free(env, dso_in, o->inputs.ndsos * sizeof(*dso_in)); + if (dso_names) + driver_free(env, dso_names, o->inputs.ndsos * sizeof(*dso_names)); + if (dso_lf) driver_free(env, dso_lf, o->inputs.ndsos * sizeof(*dso_lf)); + if (order) driver_free(env, order, o->inputs.nlink_items * sizeof(*order)); + if (obj_in) + driver_free(env, obj_in, o->inputs.nobject_files * sizeof(*obj_in)); if (obj_names) - driver_free(env, obj_names, o->nobject_files * sizeof(*obj_names)); - if (obj_lf) driver_free(env, obj_lf, o->nobject_files * sizeof(*obj_lf)); + driver_free(env, obj_names, o->inputs.nobject_files * sizeof(*obj_names)); + if (obj_lf) + driver_free(env, obj_lf, o->inputs.nobject_files * sizeof(*obj_lf)); if (src_lf) driver_free(env, src_lf, o->nsource_files * sizeof(*src_lf)); if (src_bytes) driver_free(env, src_bytes, o->nsource_files * sizeof(*src_bytes)); @@ -2741,7 +2426,7 @@ static int driver_cc_main(int argc, char** argv, int force_check) { driver_env_fini(&env); return 1; } - insert_pos = co.nlink_items; + insert_pos = co.inputs.nlink_items; /* On Windows the rt archive is inserted at TWO positions to handle two * competing requirements: * @@ -2773,13 +2458,13 @@ static int driver_cc_main(int argc, char** argv, int force_check) { uint32_t before_pos, after_pos; /* before_pos: just before the 'after' group */ - before_pos = co.nlink_items; + before_pos = co.inputs.nlink_items; { uint32_t nadj = co.hosted.nfinal + co.hosted.nafter; if (nadj <= before_pos) before_pos -= nadj; } /* after_pos: before crtend.o only (original position) */ - after_pos = co.nlink_items; + after_pos = co.inputs.nlink_items; if (co.hosted.nfinal <= after_pos) after_pos -= co.hosted.nfinal; /* Duplicate path for the second entry before ownership is transferred. @@ -2795,20 +2480,23 @@ static int driver_cc_main(int argc, char** argv, int force_check) { /* Insert later position first so it doesn't shift before_pos. */ if (rt_path2) { - CcArchiveInput* ar2 = &co.archives[co.narchives++]; + DriverArchiveInput* ar2 = &co.inputs.archives[co.inputs.narchives++]; ar2->path = rt_path2; ar2->owned = 1; ar2->owned_size = rt_path2_size; ar2->whole_archive = 0; ar2->link_mode = rt_archive.link_mode; ar2->group_id = rt_archive.group_id; - cc_insert_link_item(&co, after_pos, CC_LINK_ARCHIVE, co.narchives - 1u); + driver_link_inputs_insert(&co.inputs, after_pos, DRIVER_LINK_ARCHIVE, + co.inputs.narchives - 1u); } /* Insert earlier position (original path; ownership transferred). */ - cc_insert_runtime_archive(&co, &rt_archive, before_pos); + driver_link_inputs_insert_runtime_archive(&co.inputs, &rt_archive, + before_pos); } else { if (co.hosted.nfinal <= insert_pos) insert_pos -= co.hosted.nfinal; - cc_insert_runtime_archive(&co, &rt_archive, insert_pos); + driver_link_inputs_insert_runtime_archive(&co.inputs, &rt_archive, + insert_pos); } driver_runtime_archive_fini(&env, &rt_archive); } diff --git a/driver/driver.h b/driver/driver.h @@ -248,4 +248,10 @@ int driver_target_needs_sysroot_libdir(KitTargetSpec target); * (Windows-COFF, given a sysroot and no -nostdlib). */ int driver_target_default_hosted_profile(KitTargetSpec target); +/* Set `target->code_model` from a -mcmodel= value. Accepts the x86 spellings + * (small/medium/large) and the RISC-V aliases (medlow->small, medany->medium). + * Returns 0 on success, 1 on an unknown value (diagnostic via `tool`). */ +int driver_record_mcmodel(KitTargetSpec* target, const char* tool, + const char* val); + #endif diff --git a/driver/lib/link_inputs.c b/driver/lib/link_inputs.c @@ -0,0 +1,267 @@ +#include "link_inputs.h" + +#include <kit/core.h> + +#include "lib_resolve.h" + +int driver_link_inputs_init(DriverLinkInputSet* set, DriverEnv* env, + const char* tool, size_t bound) { + set->env = env; + set->tool = tool; + set->bound = bound; + set->object_files = + driver_alloc_zeroed(env, bound * sizeof(*set->object_files)); + set->archives = driver_alloc_zeroed(env, bound * sizeof(*set->archives)); + set->dsos = driver_alloc_zeroed(env, bound * sizeof(*set->dsos)); + set->lib_search_paths = + driver_alloc_zeroed(env, bound * sizeof(*set->lib_search_paths)); + set->pending_libs = + driver_alloc_zeroed(env, bound * sizeof(*set->pending_libs)); + set->link_items = driver_alloc_zeroed(env, bound * sizeof(*set->link_items)); + if (!set->object_files || !set->archives || !set->dsos || + !set->lib_search_paths || !set->pending_libs || !set->link_items) { + driver_errf(tool, "out of memory"); + return 1; + } + set->cur_link_mode = KIT_LM_DEFAULT; + return 0; +} + +void driver_link_inputs_fini(DriverLinkInputSet* set) { + DriverEnv* env = set->env; + size_t bound = set->bound; + uint32_t i; + for (i = 0; i < set->narchives; ++i) + if (set->archives[i].owned) + driver_free(env, (void*)set->archives[i].path, + set->archives[i].owned_size); + for (i = 0; i < set->ndsos; ++i) + if (set->dsos[i].owned) + driver_free(env, (void*)set->dsos[i].path, set->dsos[i].owned_size); + if (set->owned_sysroot_lib_dir) + driver_free(env, set->owned_sysroot_lib_dir, + set->owned_sysroot_lib_dir_size); + if (set->object_files) + driver_free(env, set->object_files, bound * sizeof(*set->object_files)); + if (set->archives) + driver_free(env, set->archives, bound * sizeof(*set->archives)); + if (set->dsos) driver_free(env, set->dsos, bound * sizeof(*set->dsos)); + if (set->lib_search_paths) + driver_free(env, set->lib_search_paths, + bound * sizeof(*set->lib_search_paths)); + if (set->pending_libs) + driver_free(env, set->pending_libs, bound * sizeof(*set->pending_libs)); + if (set->link_items) + driver_free(env, set->link_items, bound * sizeof(*set->link_items)); +} + +int driver_is_dso_path(const char* s) { + return driver_has_suffix(s, ".so") || driver_has_suffix(s, ".dylib") || + driver_has_suffix(s, ".tbd"); +} + +void driver_link_inputs_push(DriverLinkInputSet* set, uint8_t kind, + uint32_t index) { + DriverLinkItem* it = &set->link_items[set->nlink_items++]; + it->kind = kind; + it->index = index; +} + +void driver_link_inputs_insert(DriverLinkInputSet* set, uint32_t pos, + uint8_t kind, uint32_t index) { + uint32_t i; + if (pos > set->nlink_items) pos = set->nlink_items; + for (i = set->nlink_items; i > pos; --i) + set->link_items[i] = set->link_items[i - 1u]; + set->link_items[pos].kind = kind; + set->link_items[pos].index = index; + set->nlink_items++; +} + +int driver_link_inputs_append_hosted(DriverLinkInputSet* set, + const DriverHostedInput* in, + uint32_t insert_pos, int insert) { + uint32_t index; + uint8_t kind; + switch ((DriverHostedInputKind)in->kind) { + case DRIVER_HOSTED_INPUT_OBJECT: + index = set->nobject_files++; + set->object_files[index] = in->path; + kind = DRIVER_LINK_OBJECT; + break; + case DRIVER_HOSTED_INPUT_ARCHIVE: { + DriverArchiveInput* ar = &set->archives[set->narchives++]; + ar->path = in->path; + ar->whole_archive = 0; + ar->link_mode = KIT_LM_DEFAULT; + ar->group_id = 0; + index = set->narchives - 1u; + kind = DRIVER_LINK_ARCHIVE; + break; + } + case DRIVER_HOSTED_INPUT_DSO: { + DriverDsoInput* d = &set->dsos[set->ndsos++]; + d->path = in->path; + index = set->ndsos - 1u; + kind = DRIVER_LINK_DSO; + break; + } + default: + driver_errf(set->tool, "internal error: unknown hosted input kind"); + return 1; + } + if (insert) + driver_link_inputs_insert(set, insert_pos, kind, index); + else + driver_link_inputs_push(set, kind, index); + return 0; +} + +void driver_link_inputs_insert_runtime_archive(DriverLinkInputSet* set, + DriverRuntimeArchive* rt, + uint32_t insert_pos) { + DriverArchiveInput* ar = &set->archives[set->narchives++]; + ar->path = rt->path; + ar->owned = 1; + ar->owned_size = rt->path_size; + ar->whole_archive = rt->whole_archive; + ar->link_mode = rt->link_mode; + ar->group_id = rt->group_id; + rt->path = NULL; + rt->path_size = 0; + driver_link_inputs_insert(set, insert_pos, DRIVER_LINK_ARCHIVE, + set->narchives - 1u); +} + +int driver_link_inputs_resolve_pending(DriverLinkInputSet* set, + KitTargetSpec target, int static_link) { + uint32_t i; + for (i = 0; i < set->npending_libs; ++i) { + DriverPendingLib* pl = &set->pending_libs[i]; + char* p; + size_t sz; + LibResolveKind kind; + LibResolveMode mode = (static_link || pl->link_mode == KIT_LM_STATIC) + ? LIB_RESOLVE_STATIC_ONLY + : LIB_RESOLVE_DYNAMIC_PREFER; + LibResolveOS resolve_os = (target.os == KIT_OS_WINDOWS) + ? LIB_RESOLVE_OS_WINDOWS + : LIB_RESOLVE_OS_POSIX; + if (driver_lib_resolve_for_os(set->env, pl->name, mode, resolve_os, + set->lib_search_paths, set->nlib_search_paths, + &p, &sz, &kind) != 0) { + driver_errf(set->tool, "library not found: -l%.*s", + KIT_SLICE_ARG(kit_slice_cstr(pl->name))); + return 1; + } + if (kind == LIB_RESOLVE_KIND_SHARED || kind == LIB_RESOLVE_KIND_TBD) { + DriverDsoInput* d = &set->dsos[set->ndsos++]; + d->path = p; + d->owned = 1; + d->owned_size = sz; + pl->resolved_kind = DRIVER_LINK_DSO; + pl->resolved_index = set->ndsos - 1u; + } else { + DriverArchiveInput* ar = &set->archives[set->narchives++]; + ar->path = p; + ar->owned = 1; + ar->owned_size = sz; + ar->whole_archive = pl->whole_archive; + ar->link_mode = pl->link_mode; + ar->group_id = pl->group_id; + pl->resolved_kind = DRIVER_LINK_ARCHIVE; + pl->resolved_index = set->narchives - 1u; + } + } + return 0; +} + +/* The llvm-mingw UCRT sysroot ships import archives (libkernel32.a, libucrt.a, + * the UCRT API-set archives) under <sysroot>/lib; the user `-L` list is + * searched first, then this appended default. Sysroot resolution order: + * 1. -isysroot / --sysroot on the command line (already in *sysroot); + * 2. KIT_SYSROOT env var (e.g. .../x86_64-w64-mingw32). + * The appended path aliases the sysroot string for its lifetime; *sysroot is + * either argv-borrowed or env-borrowed, both stable across the driver run, so + * the lib_search_paths slot remains valid. */ +int driver_link_inputs_append_windows_lib_dirs(DriverLinkInputSet* set, + const char** sysroot, + KitTargetSpec target) { + const char* sr = *sysroot; + char* joined; + size_t srlen, need_slash, bytes, off = 0; + if (!driver_target_needs_sysroot_libdir(target)) return 0; + if (!sr || !sr[0]) { + sr = driver_getenv("KIT_SYSROOT"); + if (!sr || !sr[0]) return 0; + *sysroot = sr; + } + srlen = driver_strlen(sr); + need_slash = (srlen > 0 && sr[srlen - 1] != '/') ? 1u : 0u; + /* "<sysroot>" + "/"? + "lib" + NUL */ + bytes = srlen + need_slash + 3u + 1u; + joined = driver_alloc(set->env, bytes); + if (!joined) { + driver_errf(set->tool, "out of memory"); + return 1; + } + driver_memcpy(joined + off, sr, srlen); + off += srlen; + if (need_slash) joined[off++] = '/'; + driver_memcpy(joined + off, "lib", 3); + off += 3; + joined[off] = '\0'; + if (set->owned_sysroot_lib_dir) + driver_free(set->env, set->owned_sysroot_lib_dir, + set->owned_sysroot_lib_dir_size); + set->owned_sysroot_lib_dir = joined; + set->owned_sysroot_lib_dir_size = bytes; + set->lib_search_paths[set->nlib_search_paths++] = joined; + return 0; +} + +int driver_link_inputs_apply_hosted(DriverLinkInputSet* set, + DriverHostedPlan* plan, DriverCflags* cf, + DriverLinkFlags* link, KitTargetSpec target, + const char* sysroot, int static_link, + int no_startfiles, int link_action) { + DriverHostedRequest req = {0}; + uint32_t i; + uint32_t insert_pos = 0; + req.env = set->env; + req.tool = set->tool; + req.target = target; + req.sysroot = sysroot; + req.static_link = static_link; + req.link_inputs = link_action; + if (driver_hosted_resolve(&req, plan) != 0) return 1; + for (i = 0; i < plan->nsystem_includes; ++i) + cf->system_include_dirs[cf->nsystem_include_dirs++] = + plan->system_includes[i]; + for (i = 0; i < plan->ndefines; ++i) + cf->defines[cf->ndefines++] = plan->defines[i]; + /* Hosted lib search dirs let user -l flags (-lm, -lpthread, ...) resolve. The + * strings are owned by `plan` and outlive lib_search_paths. Insert before any + * user -L dirs so sysroot libs take precedence. */ + for (i = 0; i < plan->nlib_search_dirs; ++i) + set->lib_search_paths[set->nlib_search_paths++] = plan->lib_search_dirs[i]; + if (!link_action) return 0; + for (i = 0; i < plan->nbefore; ++i) { + if (no_startfiles) break; + if (driver_link_inputs_append_hosted(set, &plan->before[i], insert_pos, + 1) != 0) + return 1; + insert_pos++; + } + for (i = 0; i < plan->nafter; ++i) + if (driver_link_inputs_append_hosted(set, &plan->after[i], 0, 0) != 0) + return 1; + for (i = 0; i < plan->nfinal; ++i) { + if (no_startfiles) break; + if (driver_link_inputs_append_hosted(set, &plan->final[i], 0, 0) != 0) + return 1; + } + if (!link->interp_path && plan->interp_path) + link->interp_path = plan->interp_path; + return 0; +} diff --git a/driver/lib/link_inputs.h b/driver/lib/link_inputs.h @@ -0,0 +1,154 @@ +#ifndef KIT_DRIVER_LINK_INPUTS_H +#define KIT_DRIVER_LINK_INPUTS_H + +#include <kit/compile.h> +#include <stddef.h> +#include <stdint.h> + +#include "cflags.h" +#include "driver.h" +#include "hosted.h" +#include "link_flags.h" +#include "runtime.h" + +/* Shared link-input model for the `cc` and `build-*` drivers. + * + * Both drivers classify positionals (and resolved `-l` names, runtime + * archives, and hosted crt/libc files) into an ordered list of link items + * backed by parallel object / archive / dso arrays, then resolve pending `-l` + * names and replay the items into the linker. The two had byte-identical copies + * of that model and its bookkeeping; this module owns the single + * implementation. Each driver embeds a DriverLinkInputSet (by value, like the + * shared DriverCflags / DriverLinkFlags) and keeps only its tool-specific state + * (cc: sources/deps/probes; build: groups/scopes). */ + +/* Kind of a link item. SOURCE / SOURCE_MEMORY index into the *driver's own* + * source arrays (interpreted by the driver, never by this module); OBJECT / + * ARCHIVE / DSO / LIB index into this set's parallel arrays. */ +typedef enum DriverLinkKind { + DRIVER_LINK_SOURCE = 0, /* index into the driver's source array */ + DRIVER_LINK_SOURCE_MEMORY, /* cc: index into in-memory (stdin) sources */ + DRIVER_LINK_OBJECT, /* index into object_files */ + DRIVER_LINK_ARCHIVE, /* index into archives */ + DRIVER_LINK_DSO, /* index into dsos */ + DRIVER_LINK_LIB, /* index into pending_libs (resolved later) */ +} DriverLinkKind; + +typedef struct DriverLinkItem { + uint8_t kind; /* DriverLinkKind */ + uint8_t pad[3]; + uint32_t index; +} DriverLinkItem; + +typedef struct DriverArchiveInput { + const char* path; + int owned; + size_t owned_size; + uint8_t whole_archive; + uint8_t link_mode; + uint8_t group_id; + uint8_t pad; +} DriverArchiveInput; + +typedef struct DriverDsoInput { + const char* path; + int owned; + size_t owned_size; +} DriverDsoInput; + +typedef struct DriverPendingLib { + const char* name; + uint8_t whole_archive; + uint8_t link_mode; + uint8_t group_id; + uint8_t resolved_kind; /* DriverLinkKind: ARCHIVE or DSO */ + uint32_t resolved_index; +} DriverPendingLib; + +typedef struct DriverLinkInputSet { + DriverEnv* env; + const char* tool; + size_t bound; /* per-array capacity (for fini) */ + + /* Positional / resolved inputs, split by kind. */ + const char** object_files; /* .o/.obj paths */ + uint32_t nobject_files; + DriverArchiveInput* archives; /* .a paths + resolved -l names */ + uint32_t narchives; + DriverDsoInput* dsos; + uint32_t ndsos; + const char** lib_search_paths; /* -L dirs (+ hosted/sysroot dirs) */ + uint32_t nlib_search_paths; + DriverPendingLib* pending_libs; /* -l names, resolved at end-of-parse */ + uint32_t npending_libs; + DriverLinkItem* link_items; /* ordered link sequence */ + uint32_t nlink_items; + + /* Attributes applied to the next archive positional, driven by + * -Wl,--whole-archive / -Bstatic|-Bdynamic / --start-group. */ + uint8_t cur_whole_archive; + uint8_t cur_link_mode; + uint8_t cur_group_id; + + /* Owned `<sysroot>/lib` slot appended for Windows targets when a sysroot is + * in effect (see driver_link_inputs_append_windows_lib_dirs). */ + char* owned_sysroot_lib_dir; + size_t owned_sysroot_lib_dir_size; +} DriverLinkInputSet; + +/* Allocate the parallel arrays (each sized `bound`) and seed defaults + * (cur_link_mode = KIT_LM_DEFAULT). Returns 0, or 1 on OOM (diagnostic via + * `tool`). */ +int driver_link_inputs_init(DriverLinkInputSet* set, DriverEnv* env, + const char* tool, size_t bound); + +/* Free owned archive/dso paths, the owned sysroot lib dir, and the arrays. */ +void driver_link_inputs_fini(DriverLinkInputSet* set); + +/* True for a `.so` / `.dylib` / `.tbd` shared-object path. */ +int driver_is_dso_path(const char* s); + +/* Append / insert a link item referencing array slot `index`. */ +void driver_link_inputs_push(DriverLinkInputSet* set, uint8_t kind, + uint32_t index); +void driver_link_inputs_insert(DriverLinkInputSet* set, uint32_t pos, + uint8_t kind, uint32_t index); + +/* Record one hosted crt/libc input (object/archive/dso) into the set and order + * it: insert at `insert_pos` when `insert`, else append. Returns 0/1. */ +int driver_link_inputs_append_hosted(DriverLinkInputSet* set, + const DriverHostedInput* in, + uint32_t insert_pos, int insert); + +/* Move a runtime archive (ownership transferred out of `rt`) into the set and + * insert its link item at `insert_pos`. */ +void driver_link_inputs_insert_runtime_archive(DriverLinkInputSet* set, + DriverRuntimeArchive* rt, + uint32_t insert_pos); + +/* Resolve every pending `-l` name against lib_search_paths into a concrete + * archive or dso slot, filling each pending lib's resolved_kind/index. Returns + * 0, or 1 with a diagnostic on not-found. */ +int driver_link_inputs_resolve_pending(DriverLinkInputSet* set, + KitTargetSpec target, int static_link); + +/* For Windows targets, append `<sysroot>/lib` to the search path. The sysroot + * is `*sysroot` if set, else KIT_SYSROOT (which is then written back through + * `*sysroot`). No-op for non-Windows targets or when no sysroot applies. + * Returns 0/1. */ +int driver_link_inputs_append_windows_lib_dirs(DriverLinkInputSet* set, + const char** sysroot, + KitTargetSpec target); + +/* Apply a hosted libc profile: resolve `plan` for the target/sysroot, add its + * system includes + defines to `cf`, add its lib search dirs to the set, and + * (when `link_action`) insert its crt inputs and adopt its interpreter into + * `link`. The wants-hosted / -nostdlib guard belongs to the caller. Returns + * 0/1. */ +int driver_link_inputs_apply_hosted(DriverLinkInputSet* set, + DriverHostedPlan* plan, DriverCflags* cf, + DriverLinkFlags* link, KitTargetSpec target, + const char* sysroot, int static_link, + int no_startfiles, int link_action); + +#endif diff --git a/driver/lib/target.c b/driver/lib/target.c @@ -485,3 +485,22 @@ int driver_target_to_triple(KitTargetSpec target, char* buf, size_t cap) { KIT_SLICE_ARG(kit_slice_cstr(os))); return n < 0 || (size_t)n >= cap; } + +int driver_record_mcmodel(KitTargetSpec* target, const char* tool, + const char* val) { + if (driver_streq(val, "small") || driver_streq(val, "medlow")) { + target->code_model = KIT_CM_SMALL; + return 0; + } + if (driver_streq(val, "medium") || driver_streq(val, "medany")) { + target->code_model = KIT_CM_MEDIUM; + return 0; + } + if (driver_streq(val, "large")) { + target->code_model = KIT_CM_LARGE; + return 0; + } + driver_errf(tool, "unknown -mcmodel value: %.*s", + KIT_SLICE_ARG(kit_slice_cstr(val))); + return 1; +} diff --git a/mk/driver_srcs.mk b/mk/driver_srcs.mk @@ -71,6 +71,7 @@ DRIVER_SRCS += $(call need-any,AR RANLIB STRIP DBG RUN BUILD_EXE BUILD_LIB BUILD DRIVER_SRCS += $(call need-any,STRIP OBJCOPY,driver/lib/objedit.c) DRIVER_SRCS += $(call need-any,RUN,driver/lib/wasm_run.c) DRIVER_SRCS += $(call need-any,CC CHECK BUILD_EXE BUILD_LIB BUILD_OBJ,driver/lib/compile_engine.c) +DRIVER_SRCS += $(call need-any,CC CHECK BUILD_EXE BUILD_LIB BUILD_OBJ,driver/lib/link_inputs.c) DRIVER_SRCS += $(call need-any,CAS PKG,driver/lib/dist_host.c) DRIVER_SRCS += $(call need-any,ADDR2LINE SYMBOLIZE,driver/lib/dwarfsym.c) # backtrace.c (FP-walk kernel + symbolized printer) is consumed by the dbg/run