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:
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