compile_engine.c (8198B)
1 #include "compile_engine.h" 2 3 #include <kit/asm_emit.h> 4 #include <kit/cg.h> 5 #include <string.h> 6 7 static KitStatus driver_compile_cg_run(KitCompiler* compiler, 8 const KitCodeOptions* code, 9 const KitDiagnosticOptions* diagnostics, 10 const DriverCompileSource* src, 11 KitCg* cg) { 12 KitCompileSessionOptions sopts; 13 KitCompileSession* session = NULL; 14 KitSourceInput sin; 15 KitStatus st; 16 17 if (!compiler || !code || !diagnostics || !src || !cg) return KIT_INVALID; 18 memset(&sopts, 0, sizeof(sopts)); 19 sopts.lang = src->lang; 20 sopts.compile.code = *code; 21 sopts.compile.diagnostics = *diagnostics; 22 if (src->pp) sopts.compile.preprocess = *src->pp; 23 sopts.compile.language_options = src->lang_extra; 24 25 memset(&sin, 0, sizeof(sin)); 26 sin.name = src->name; 27 sin.bytes = src->bytes; 28 sin.lang = src->lang; 29 30 st = kit_compile_session_new(compiler, &sopts, &session); 31 if (st == KIT_OK) st = kit_compile_session_compile_cg(session, &sin, cg); 32 kit_compile_session_free(session); 33 return st; 34 } 35 36 KitStatus driver_compile_run(KitCompiler* compiler, KitLanguage lang, 37 const KitCodeOptions* code, 38 const KitDiagnosticOptions* diagnostics, 39 const KitPreprocessOptions* pp, 40 const void* lang_extra, KitSlice name, 41 const KitSlice* bytes, KitWriter* emit_out, 42 KitObjBuilder** obj_out) { 43 KitCompileSessionOptions sopts; 44 KitCompileSession* session = NULL; 45 KitSourceInput sin; 46 KitObjBuilder* ob = NULL; 47 KitCodeOptions code_copy = *code; 48 KitStatus st; 49 50 if (obj_out) *obj_out = NULL; 51 52 /* For the in-CG emit modes the output writer is consumed during codegen, so 53 * wire it onto the code options before the session runs. */ 54 if (emit_out && code_copy.emit_c_source) code_copy.c_source_writer = emit_out; 55 if (emit_out && code_copy.emit_ir) code_copy.ir_dump_writer = emit_out; 56 57 memset(&sopts, 0, sizeof(sopts)); 58 sopts.lang = lang; 59 sopts.compile.code = code_copy; 60 sopts.compile.diagnostics = *diagnostics; 61 if (pp) sopts.compile.preprocess = *pp; 62 sopts.compile.language_options = lang_extra; 63 64 memset(&sin, 0, sizeof(sin)); 65 sin.name = name; 66 sin.bytes = *bytes; 67 sin.lang = lang; 68 69 st = kit_compile_session_new(compiler, &sopts, &session); 70 if (st == KIT_OK) st = kit_compile_session_compile(session, &sin, &ob); 71 kit_compile_session_free(session); 72 if (st != KIT_OK) return st; 73 74 if (obj_out) { 75 *obj_out = ob; 76 return KIT_OK; 77 } 78 79 /* emit_out path: serialize by output mode. The in-CG modes already wrote 80 * through the wired writer above. */ 81 if (code_copy.emit_c_source || code_copy.emit_ir) { 82 /* nothing to serialize here */ 83 } else if (code_copy.emit_asm_source) { 84 st = kit_obj_builder_emit_asm(ob, emit_out); 85 } else { 86 st = kit_obj_builder_emit(ob, emit_out); 87 } 88 kit_obj_builder_free(ob); 89 return st; 90 } 91 92 static int driver_compile_lto_enabled(const KitCodeOptions* code) { 93 return code && code->lto && !code->check_only && !code->emit_c_source && 94 !code->emit_ir && !code->emit_asm_source; 95 } 96 97 static KitStatus driver_compile_start_lto(KitCompiler* compiler, 98 const KitCodeOptions* code, 99 KitObjBuilder** ob_out, 100 KitCg** cg_out) { 101 KitObjBuilder* ob = NULL; 102 KitCg* cg = NULL; 103 KitStatus st; 104 105 if (ob_out) *ob_out = NULL; 106 if (cg_out) *cg_out = NULL; 107 if (!compiler || !code || !ob_out || !cg_out) return KIT_INVALID; 108 st = kit_obj_builder_new(compiler, &ob); 109 if (st == KIT_OK) st = kit_cg_new(compiler, &cg); 110 if (st == KIT_OK) st = kit_cg_begin(cg, ob, code); 111 if (st != KIT_OK) { 112 kit_cg_free(cg); 113 kit_obj_builder_free(ob); 114 return st; 115 } 116 *ob_out = ob; 117 *cg_out = cg; 118 return KIT_OK; 119 } 120 121 KitStatus driver_compile_pending_lto_finish( 122 DriverCompilePendingLto* pending, const DriverCompileBatchOptions* batch, 123 const KitCgSym* preserved_symbols, uint32_t npreserved_symbols) { 124 KitCgFinishOptions finish; 125 KitStatus st; 126 127 if (!pending || !pending->active) return KIT_OK; 128 if (!pending->obj || !pending->cg) { 129 driver_compile_pending_lto_abort(pending); 130 return KIT_INVALID; 131 } 132 133 memset(&finish, 0, sizeof finish); 134 finish.output_kind = batch ? batch->output_kind : KIT_CG_OUTPUT_RELOCATABLE; 135 finish.interposition_policy = 136 batch ? batch->interposition_policy : KIT_CG_INTERPOSITION_DEFAULT; 137 finish.preserved_symbols = preserved_symbols; 138 finish.npreserved_symbols = npreserved_symbols; 139 140 st = kit_cg_finish(pending->cg, &finish); 141 if (st == KIT_OK) st = kit_cg_detach(pending->cg); 142 if (st == KIT_OK) st = kit_obj_builder_finalize(pending->obj); 143 144 kit_cg_free(pending->cg); 145 pending->cg = NULL; 146 pending->active = 0; 147 return st; 148 } 149 150 void driver_compile_pending_lto_abort(DriverCompilePendingLto* pending) { 151 if (!pending || !pending->active) return; 152 kit_cg_free(pending->cg); 153 pending->cg = NULL; 154 pending->active = 0; 155 } 156 157 KitStatus driver_compile_sources_run(KitCompiler* compiler, 158 const KitCodeOptions* code, 159 const KitDiagnosticOptions* diagnostics, 160 const DriverCompileSource* sources, 161 uint32_t nsources, 162 const DriverCompileBatchOptions* batch, 163 DriverCompileObjects* out) { 164 DriverCompilePendingLto pending_lto; 165 int lto_order_emitted = 0; 166 int lto_enabled = driver_compile_lto_enabled(code); 167 KitStatus st = KIT_OK; 168 169 if (!compiler || !code || !diagnostics || (!sources && nsources) || !out || 170 !out->objs || !out->source_obj_index || !out->source_order_keep) { 171 return KIT_INVALID; 172 } 173 memset(&pending_lto, 0, sizeof pending_lto); 174 out->nobjs = 0; 175 if (out->pending_lto) memset(out->pending_lto, 0, sizeof(*out->pending_lto)); 176 for (uint32_t i = 0; i < nsources; ++i) { 177 out->source_obj_index[i] = (uint32_t)-1; 178 out->source_order_keep[i] = 0; 179 } 180 181 for (uint32_t i = 0; i < nsources; ++i) { 182 const DriverCompileSource* src = &sources[i]; 183 KitFrontendCaps caps; 184 int stage_cg = 0; 185 186 memset(&caps, 0, sizeof caps); 187 if (lto_enabled) { 188 st = kit_frontend_caps(compiler, src->lang, &caps); 189 if (st != KIT_OK) goto out; 190 stage_cg = caps.lto_mode == KIT_FRONTEND_LTO_CG; 191 } 192 193 if (stage_cg) { 194 if (!pending_lto.active) { 195 st = driver_compile_start_lto(compiler, code, &pending_lto.obj, 196 &pending_lto.cg); 197 if (st != KIT_OK) goto out; 198 pending_lto.obj_index = out->nobjs; 199 pending_lto.active = 1; 200 out->objs[out->nobjs++] = pending_lto.obj; 201 } 202 out->source_obj_index[i] = pending_lto.obj_index; 203 if (!lto_order_emitted) { 204 out->source_order_keep[i] = 1; 205 lto_order_emitted = 1; 206 } 207 st = driver_compile_cg_run(compiler, code, diagnostics, src, 208 pending_lto.cg); 209 if (st != KIT_OK) goto out; 210 continue; 211 } 212 213 { 214 KitObjBuilder* ob = NULL; 215 st = driver_compile_run(compiler, src->lang, code, diagnostics, src->pp, 216 src->lang_extra, src->name, &src->bytes, NULL, 217 &ob); 218 if (st != KIT_OK) goto out; 219 out->source_obj_index[i] = out->nobjs; 220 out->source_order_keep[i] = 1; 221 out->objs[out->nobjs++] = ob; 222 } 223 } 224 225 if (pending_lto.active) { 226 if (batch && batch->defer_lto_finish) { 227 if (!out->pending_lto) { 228 st = KIT_INVALID; 229 goto out; 230 } 231 *out->pending_lto = pending_lto; 232 memset(&pending_lto, 0, sizeof pending_lto); 233 } else { 234 st = driver_compile_pending_lto_finish(&pending_lto, batch, NULL, 0); 235 if (st != KIT_OK) goto out; 236 } 237 } 238 239 out: 240 if (pending_lto.active) driver_compile_pending_lto_abort(&pending_lto); 241 return st; 242 }