link_inputs.h (9741B)
1 #ifndef KIT_DRIVER_LINK_INPUTS_H 2 #define KIT_DRIVER_LINK_INPUTS_H 3 4 #include <kit/compile.h> 5 #include <stddef.h> 6 #include <stdint.h> 7 8 #include "cflags.h" 9 #include "driver.h" 10 #include "hosted.h" 11 #include "link_flags.h" 12 #include "runtime.h" 13 14 /* Shared link-input model for the `cc` and `build-*` drivers. 15 * 16 * Both drivers classify positionals (and resolved `-l` names, runtime 17 * archives, and hosted crt/libc files) into an ordered list of link items 18 * backed by parallel object / archive / dso arrays, then resolve pending `-l` 19 * names and replay the items into the linker. The two had byte-identical copies 20 * of that model and its bookkeeping; this module owns the single 21 * implementation. Each driver embeds a DriverLinkInputSet (by value, like the 22 * shared DriverCflags / DriverLinkFlags) and keeps only its tool-specific state 23 * (cc: sources/deps/probes; build: groups/scopes). */ 24 25 /* Kind of a link item. SOURCE / SOURCE_MEMORY index into the *driver's own* 26 * source arrays (interpreted by the driver, never by this module); OBJECT / 27 * ARCHIVE / DSO / LIB index into this set's parallel arrays. */ 28 typedef enum DriverLinkKind { 29 DRIVER_LINK_SOURCE = 0, /* index into the driver's source array */ 30 DRIVER_LINK_SOURCE_MEMORY, /* cc: index into in-memory (stdin) sources */ 31 DRIVER_LINK_OBJECT, /* index into object_files */ 32 DRIVER_LINK_ARCHIVE, /* index into archives */ 33 DRIVER_LINK_DSO, /* index into dsos */ 34 DRIVER_LINK_LIB, /* index into pending_libs (resolved later) */ 35 DRIVER_LINK_FRAMEWORK, /* index into pending_frameworks */ 36 } DriverLinkKind; 37 38 typedef struct DriverLinkItem { 39 uint8_t kind; /* DriverLinkKind */ 40 uint8_t pad[3]; 41 uint32_t index; 42 } DriverLinkItem; 43 44 typedef struct DriverArchiveInput { 45 const char* path; 46 int owned; 47 size_t owned_size; 48 uint8_t whole_archive; 49 uint8_t link_mode; 50 uint8_t group_id; 51 uint8_t pad; 52 } DriverArchiveInput; 53 54 typedef struct DriverDsoInput { 55 const char* path; 56 int owned; 57 size_t owned_size; 58 } DriverDsoInput; 59 60 typedef struct DriverPendingLib { 61 const char* name; 62 uint8_t whole_archive; 63 uint8_t link_mode; 64 uint8_t group_id; 65 uint8_t resolved_kind; /* DriverLinkKind: ARCHIVE or DSO */ 66 uint32_t resolved_index; 67 } DriverPendingLib; 68 69 typedef struct DriverPendingFramework { 70 const char* name; 71 uint32_t resolved_index; 72 } DriverPendingFramework; 73 74 typedef struct DriverLinkInputSet { 75 DriverEnv* env; 76 const char* tool; 77 size_t bound; /* per-array capacity (for fini) */ 78 79 /* Positional / resolved inputs, split by kind. */ 80 const char** object_files; /* .o/.obj paths */ 81 uint32_t nobject_files; 82 DriverArchiveInput* archives; /* .a paths + resolved -l names */ 83 uint32_t narchives; 84 DriverDsoInput* dsos; 85 uint32_t ndsos; 86 const char** lib_search_paths; /* -L dirs (+ hosted/sysroot dirs) */ 87 uint32_t nlib_search_paths; 88 const char** framework_search_paths; /* -F dirs (+ SDK framework dirs) */ 89 uint32_t nframework_search_paths; 90 DriverPendingLib* pending_libs; /* -l names, resolved at end-of-parse */ 91 uint32_t npending_libs; 92 DriverPendingFramework* pending_frameworks; /* -framework names */ 93 uint32_t npending_frameworks; 94 DriverLinkItem* link_items; /* ordered link sequence */ 95 uint32_t nlink_items; 96 97 /* Attributes applied to the next archive positional, driven by 98 * -Wl,--whole-archive / -Bstatic|-Bdynamic / --start-group. */ 99 uint8_t cur_whole_archive; 100 uint8_t cur_link_mode; 101 uint8_t cur_group_id; 102 103 /* Owned `<sysroot>/lib` slot appended for Windows targets when a sysroot is 104 * in effect (see driver_link_inputs_append_windows_lib_dirs). */ 105 char* owned_sysroot_lib_dir; 106 size_t owned_sysroot_lib_dir_size; 107 char* owned_sysroot_framework_dirs[2]; 108 size_t owned_sysroot_framework_dir_sizes[2]; 109 uint32_t nowned_sysroot_framework_dirs; 110 } DriverLinkInputSet; 111 112 /* Allocate the parallel arrays (each sized `bound`) and seed defaults 113 * (cur_link_mode = KIT_LM_DEFAULT). Returns 0, or 1 on OOM (diagnostic via 114 * `tool`). */ 115 int driver_link_inputs_init(DriverLinkInputSet* set, DriverEnv* env, 116 const char* tool, size_t bound); 117 118 /* Free owned archive/dso paths, the owned sysroot lib dir, and the arrays. */ 119 void driver_link_inputs_fini(DriverLinkInputSet* set); 120 121 /* True for a `.so` / `.dylib` / `.tbd` shared-object path. */ 122 int driver_is_dso_path(const char* s); 123 124 /* Append / insert a link item referencing array slot `index`. */ 125 void driver_link_inputs_push(DriverLinkInputSet* set, uint8_t kind, 126 uint32_t index); 127 void driver_link_inputs_insert(DriverLinkInputSet* set, uint32_t pos, 128 uint8_t kind, uint32_t index); 129 130 /* Record one hosted crt/libc input (object/archive/dso) into the set and order 131 * it: insert at `insert_pos` when `insert`, else append. Returns 0/1. */ 132 int driver_link_inputs_append_hosted(DriverLinkInputSet* set, 133 const DriverHostedInput* in, 134 uint32_t insert_pos, int insert); 135 136 /* Move a runtime archive (ownership transferred out of `rt`) into the set and 137 * insert its link item at `insert_pos`. */ 138 void driver_link_inputs_insert_runtime_archive(DriverLinkInputSet* set, 139 DriverRuntimeArchive* rt, 140 uint32_t insert_pos); 141 142 /* Insert the compiler runtime archive `rt` (ownership transferred out) at the 143 * position(s) that satisfy the target's link order. For Windows this is a 144 * two-position insert (a strong-_setjmp entry before the hosted `after` group 145 * plus a late ___chkstk_ms entry before crtend; see the implementation), so a 146 * second owned copy of the path is allocated. For every other target it is the 147 * single end-insert (before the `nfinal` crt-end group). `nfinal` / `nafter` 148 * are the hosted plan's final / after group sizes. */ 149 void driver_link_inputs_insert_runtime_archives(DriverLinkInputSet* set, 150 DriverRuntimeArchive* rt, 151 KitTargetSpec target, 152 uint32_t nfinal, 153 uint32_t nafter); 154 155 /* Translate the recorded link-item sequence into the engine's public 156 * KitLinkInputOrder list, writing into `order` (sized >= set->nlink_items) and 157 * returning the count produced. SOURCE / SOURCE_MEMORY items index the caller's 158 * parallel `source_obj_index` / `source_order_keep` arrays — the latter gates 159 * whether a compiled source survived DCE; dropped sources are skipped. 160 * SOURCE_MEMORY (cc stdin sources) indexes past `nsource_files` into those same 161 * arrays; build records no SOURCE_MEMORY items, so it may pass any 162 * nsource_files. OBJECT / ARCHIVE / DSO map straight through; LIB resolves via 163 * its pending-lib slot's resolved kind/index. */ 164 uint32_t driver_link_inputs_build_order(const DriverLinkInputSet* set, 165 const uint32_t* source_obj_index, 166 const uint8_t* source_order_keep, 167 uint32_t nsource_files, 168 KitLinkInputOrder* order); 169 170 /* Resolve every pending `-l` name against lib_search_paths into a concrete 171 * archive or dso slot, filling each pending lib's resolved_kind/index. Returns 172 * 0, or 1 with a diagnostic on not-found. */ 173 int driver_link_inputs_resolve_pending(DriverLinkInputSet* set, 174 KitTargetSpec target, int static_link); 175 176 /* For Windows targets, append `<sysroot>/lib` to the search path. The sysroot 177 * is `*sysroot` if set, else KIT_SYSROOT (which is then written back through 178 * `*sysroot`). No-op for non-Windows targets or when no sysroot applies. 179 * Returns 0/1. */ 180 int driver_link_inputs_append_windows_lib_dirs(DriverLinkInputSet* set, 181 const char** sysroot, 182 KitTargetSpec target); 183 184 /* True when the target uses Mach-O framework search dirs (Apple SDK): obj is 185 * Mach-O and the target OS's hosted ops set uses_framework_dirs. Shared between 186 * the cc/build link-input path and the `ld` driver. */ 187 int driver_target_uses_framework_dirs(KitTargetSpec target); 188 189 /* For Mach-O SDK targets, append `<sysroot>/System/Library/Frameworks` and 190 * `<sysroot>/System/Library/PrivateFrameworks` to the framework search path. 191 * The sysroot is `*sysroot` if set, else KIT_SYSROOT (which is written back 192 * through `*sysroot`). No-op for non-Apple-Mach-O targets or no sysroot. */ 193 int driver_link_inputs_append_sysroot_framework_dirs(DriverLinkInputSet* set, 194 const char** sysroot, 195 KitTargetSpec target); 196 197 /* Apply a hosted libc profile: resolve `plan` for the target/sysroot, add its 198 * system includes + defines to `cf`, add its lib search dirs to the set, and 199 * (when `link_action`) insert its crt inputs and adopt its interpreter into 200 * `link`. The wants-hosted / -nostdlib guard belongs to the caller. Returns 201 * 0/1. */ 202 int driver_link_inputs_apply_hosted(DriverLinkInputSet* set, 203 DriverHostedPlan* plan, DriverCflags* cf, 204 DriverLinkFlags* link, KitTargetSpec target, 205 const char* sysroot, int static_link, 206 int shared_link, int no_startfiles, 207 int link_action); 208 209 #endif