authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-10-23 13:18:22-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-10-23 20:05:12-07:00
log4f04759c874d5fd41c7cadeb974b4459559bc2a7
treee3a5e2f56b6ede2f4aa8c71d59856b42f48761c2
parent828735ac036abba77ffce2bf963c04f99f1687c8

build: add `-Donly-c` option

This option can be used to produce a C backend build of the self-hosted compiler, which only has the C backend enabled. Once the C backend is capable of self-hosting, this will be a way for us to replace our stage1 codebase with a C backend build of self-hosted, which we can then use for bootstrapping. See #5246 for more details. Using this option right now results in a crash because the C backend is not yet passing all the behavior tests.

3 files changed, 91 insertions(+), 14 deletions(-)

build.zig+9-1
...@@ -48,6 +48,8 @@ pub fn build(b: *Builder) !void {...@@ -48,6 +48,8 @@ pub fn build(b: *Builder) !void {
4848
49 const fmt_build_zig = b.addFmt(&[_][]const u8{"build.zig"});49 const fmt_build_zig = b.addFmt(&[_][]const u8{"build.zig"});
5050
51 const only_c = b.option(bool, "only-c", "Translate the Zig compiler to C code, with only the C backend enabled") orelse false;
52
51 const skip_debug = b.option(bool, "skip-debug", "Main test suite skips debug builds") orelse false;53 const skip_debug = b.option(bool, "skip-debug", "Main test suite skips debug builds") orelse false;
52 const skip_release = b.option(bool, "skip-release", "Main test suite skips release builds") orelse false;54 const skip_release = b.option(bool, "skip-release", "Main test suite skips release builds") orelse false;
53 const skip_release_small = b.option(bool, "skip-release-small", "Main test suite skips release-small builds") orelse skip_release;55 const skip_release_small = b.option(bool, "skip-release-small", "Main test suite skips release-small builds") orelse skip_release;
...@@ -123,7 +125,7 @@ pub fn build(b: *Builder) !void {...@@ -123,7 +125,7 @@ pub fn build(b: *Builder) !void {
123 const tracy_callstack = b.option(bool, "tracy-callstack", "Include callstack information with Tracy data. Does nothing if -Dtracy is not provided") orelse false;125 const tracy_callstack = b.option(bool, "tracy-callstack", "Include callstack information with Tracy data. Does nothing if -Dtracy is not provided") orelse false;
124 const tracy_allocation = b.option(bool, "tracy-allocation", "Include allocation information with Tracy data. Does nothing if -Dtracy is not provided") orelse false;126 const tracy_allocation = b.option(bool, "tracy-allocation", "Include allocation information with Tracy data. Does nothing if -Dtracy is not provided") orelse false;
125 const force_gpa = b.option(bool, "force-gpa", "Force the compiler to use GeneralPurposeAllocator") orelse false;127 const force_gpa = b.option(bool, "force-gpa", "Force the compiler to use GeneralPurposeAllocator") orelse false;
126 const link_libc = b.option(bool, "force-link-libc", "Force self-hosted compiler to link libc") orelse enable_llvm;128 const link_libc = b.option(bool, "force-link-libc", "Force self-hosted compiler to link libc") orelse (enable_llvm or only_c);
127 const sanitize_thread = b.option(bool, "sanitize-thread", "Enable thread-sanitization") orelse false;129 const sanitize_thread = b.option(bool, "sanitize-thread", "Enable thread-sanitization") orelse false;
128 const strip = b.option(bool, "strip", "Omit debug information") orelse false;130 const strip = b.option(bool, "strip", "Omit debug information") orelse false;
129 const use_zig0 = b.option(bool, "zig0", "Bootstrap using zig0") orelse false;131 const use_zig0 = b.option(bool, "zig0", "Bootstrap using zig0") orelse false;
...@@ -166,6 +168,10 @@ pub fn build(b: *Builder) !void {...@@ -166,6 +168,10 @@ pub fn build(b: *Builder) !void {
166 test_cases.want_lto = false;168 test_cases.want_lto = false;
167 }169 }
168170
171 if (only_c) {
172 exe.ofmt = .c;
173 }
174
169 const exe_options = b.addOptions();175 const exe_options = b.addOptions();
170 exe.addOptions("build_options", exe_options);176 exe.addOptions("build_options", exe_options);
171177
...@@ -176,6 +182,7 @@ pub fn build(b: *Builder) !void {...@@ -176,6 +182,7 @@ pub fn build(b: *Builder) !void {
176 exe_options.addOption(bool, "llvm_has_csky", llvm_has_csky);182 exe_options.addOption(bool, "llvm_has_csky", llvm_has_csky);
177 exe_options.addOption(bool, "llvm_has_arc", llvm_has_arc);183 exe_options.addOption(bool, "llvm_has_arc", llvm_has_arc);
178 exe_options.addOption(bool, "force_gpa", force_gpa);184 exe_options.addOption(bool, "force_gpa", force_gpa);
185 exe_options.addOption(bool, "only_c", only_c);
179186
180 if (link_libc) {187 if (link_libc) {
181 exe.linkLibC();188 exe.linkLibC();
...@@ -408,6 +415,7 @@ pub fn build(b: *Builder) !void {...@@ -408,6 +415,7 @@ pub fn build(b: *Builder) !void {
408 test_cases_options.addOption(bool, "llvm_has_csky", llvm_has_csky);415 test_cases_options.addOption(bool, "llvm_has_csky", llvm_has_csky);
409 test_cases_options.addOption(bool, "llvm_has_arc", llvm_has_arc);416 test_cases_options.addOption(bool, "llvm_has_arc", llvm_has_arc);
410 test_cases_options.addOption(bool, "force_gpa", force_gpa);417 test_cases_options.addOption(bool, "force_gpa", force_gpa);
418 test_cases_options.addOption(bool, "only_c", only_c);
411 test_cases_options.addOption(bool, "enable_qemu", b.enable_qemu);419 test_cases_options.addOption(bool, "enable_qemu", b.enable_qemu);
412 test_cases_options.addOption(bool, "enable_wine", b.enable_wine);420 test_cases_options.addOption(bool, "enable_wine", b.enable_wine);
413 test_cases_options.addOption(bool, "enable_wasmtime", b.enable_wasmtime);421 test_cases_options.addOption(bool, "enable_wasmtime", b.enable_wasmtime);
src/config.zig.in+1
...@@ -10,3 +10,4 @@ pub const enable_tracy = false;...@@ -10,3 +10,4 @@ pub const enable_tracy = false;
10pub const value_tracing = false;10pub const value_tracing = false;
11pub const have_stage1 = true;11pub const have_stage1 = true;
12pub const skip_non_native = false;12pub const skip_non_native = false;
13pub const only_c = false;
src/link.zig+81-13
...@@ -284,7 +284,8 @@ pub const File = struct {...@@ -284,7 +284,8 @@ pub const File = struct {
284 /// rewriting it. A malicious file is detected as incremental link failure284 /// rewriting it. A malicious file is detected as incremental link failure
285 /// and does not cause Illegal Behavior. This operation is not atomic.285 /// and does not cause Illegal Behavior. This operation is not atomic.
286 pub fn openPath(allocator: Allocator, options: Options) !*File {286 pub fn openPath(allocator: Allocator, options: Options) !*File {
287 if (options.target.ofmt == .macho) {287 const have_macho = !build_options.only_c;
288 if (have_macho and options.target.ofmt == .macho) {
288 return &(try MachO.openPath(allocator, options)).base;289 return &(try MachO.openPath(allocator, options)).base;
289 }290 }
290291
...@@ -332,18 +333,40 @@ pub const File = struct {...@@ -332,18 +333,40 @@ pub const File = struct {
332 } else emit.sub_path;333 } else emit.sub_path;
333 errdefer if (use_lld) allocator.free(sub_path);334 errdefer if (use_lld) allocator.free(sub_path);
334335
335 const file: *File = switch (options.target.ofmt) {336 const file: *File = f: {
336 .coff => &(try Coff.openPath(allocator, sub_path, options)).base,337 switch (options.target.ofmt) {
337 .elf => &(try Elf.openPath(allocator, sub_path, options)).base,338 .coff => {
338 .macho => unreachable,339 if (build_options.only_c) unreachable;
339 .plan9 => &(try Plan9.openPath(allocator, sub_path, options)).base,340 break :f &(try Coff.openPath(allocator, sub_path, options)).base;
340 .wasm => &(try Wasm.openPath(allocator, sub_path, options)).base,341 },
341 .c => &(try C.openPath(allocator, sub_path, options)).base,342 .elf => {
342 .spirv => &(try SpirV.openPath(allocator, sub_path, options)).base,343 if (build_options.only_c) unreachable;
343 .nvptx => &(try NvPtx.openPath(allocator, sub_path, options)).base,344 break :f &(try Elf.openPath(allocator, sub_path, options)).base;
344 .hex => return error.HexObjectFormatUnimplemented,345 },
345 .raw => return error.RawObjectFormatUnimplemented,346 .macho => unreachable,
346 .dxcontainer => return error.DirectXContainerObjectFormatUnimplemented,347 .plan9 => {
348 if (build_options.only_c) unreachable;
349 break :f &(try Plan9.openPath(allocator, sub_path, options)).base;
350 },
351 .wasm => {
352 if (build_options.only_c) unreachable;
353 break :f &(try Wasm.openPath(allocator, sub_path, options)).base;
354 },
355 .c => {
356 break :f &(try C.openPath(allocator, sub_path, options)).base;
357 },
358 .spirv => {
359 if (build_options.only_c) unreachable;
360 break :f &(try SpirV.openPath(allocator, sub_path, options)).base;
361 },
362 .nvptx => {
363 if (build_options.only_c) unreachable;
364 break :f &(try NvPtx.openPath(allocator, sub_path, options)).base;
365 },
366 .hex => return error.HexObjectFormatUnimplemented,
367 .raw => return error.RawObjectFormatUnimplemented,
368 .dxcontainer => return error.DirectXContainerObjectFormatUnimplemented,
369 }
347 };370 };
348371
349 if (use_lld) {372 if (use_lld) {
...@@ -366,6 +389,7 @@ pub const File = struct {...@@ -366,6 +389,7 @@ pub const File = struct {
366 pub fn makeWritable(base: *File) !void {389 pub fn makeWritable(base: *File) !void {
367 switch (base.tag) {390 switch (base.tag) {
368 .coff, .elf, .macho, .plan9, .wasm => {391 .coff, .elf, .macho, .plan9, .wasm => {
392 if (build_options.only_c) unreachable;
369 if (base.file != null) return;393 if (base.file != null) return;
370 const emit = base.options.emit orelse return;394 const emit = base.options.emit orelse return;
371 base.file = try emit.directory.handle.createFile(emit.sub_path, .{395 base.file = try emit.directory.handle.createFile(emit.sub_path, .{
...@@ -389,6 +413,7 @@ pub const File = struct {...@@ -389,6 +413,7 @@ pub const File = struct {
389 }413 }
390 switch (base.tag) {414 switch (base.tag) {
391 .macho => if (base.file) |f| {415 .macho => if (base.file) |f| {
416 if (build_options.only_c) unreachable;
392 if (comptime builtin.target.isDarwin() and builtin.target.cpu.arch == .aarch64) {417 if (comptime builtin.target.isDarwin() and builtin.target.cpu.arch == .aarch64) {
393 if (base.options.target.cpu.arch == .aarch64) {418 if (base.options.target.cpu.arch == .aarch64) {
394 // XNU starting with Big Sur running on arm64 is caching inodes of running binaries.419 // XNU starting with Big Sur running on arm64 is caching inodes of running binaries.
...@@ -407,6 +432,7 @@ pub const File = struct {...@@ -407,6 +432,7 @@ pub const File = struct {
407 base.file = null;432 base.file = null;
408 },433 },
409 .coff, .elf, .plan9, .wasm => if (base.file) |f| {434 .coff, .elf, .plan9, .wasm => if (base.file) |f| {
435 if (build_options.only_c) unreachable;
410 if (base.intermediary_basename != null) {436 if (base.intermediary_basename != null) {
411 // The file we have open is not the final file that we want to437 // The file we have open is not the final file that we want to
412 // make executable, so we don't have to close it.438 // make executable, so we don't have to close it.
...@@ -454,6 +480,7 @@ pub const File = struct {...@@ -454,6 +480,7 @@ pub const File = struct {
454 /// constant. Returns the symbol index of the lowered constant in the read-only section480 /// constant. Returns the symbol index of the lowered constant in the read-only section
455 /// of the final binary.481 /// of the final binary.
456 pub fn lowerUnnamedConst(base: *File, tv: TypedValue, decl_index: Module.Decl.Index) UpdateDeclError!u32 {482 pub fn lowerUnnamedConst(base: *File, tv: TypedValue, decl_index: Module.Decl.Index) UpdateDeclError!u32 {
483 if (build_options.only_c) @compileError("unreachable");
457 const decl = base.options.module.?.declPtr(decl_index);484 const decl = base.options.module.?.declPtr(decl_index);
458 log.debug("lowerUnnamedConst {*} ({s})", .{ decl, decl.name });485 log.debug("lowerUnnamedConst {*} ({s})", .{ decl, decl.name });
459 switch (base.tag) {486 switch (base.tag) {
...@@ -474,6 +501,7 @@ pub const File = struct {...@@ -474,6 +501,7 @@ pub const File = struct {
474 /// If no symbol exists yet with this name, a new undefined global symbol will501 /// If no symbol exists yet with this name, a new undefined global symbol will
475 /// be created. This symbol may get resolved once all relocatables are (re-)linked.502 /// be created. This symbol may get resolved once all relocatables are (re-)linked.
476 pub fn getGlobalSymbol(base: *File, name: []const u8) UpdateDeclError!u32 {503 pub fn getGlobalSymbol(base: *File, name: []const u8) UpdateDeclError!u32 {
504 if (build_options.only_c) @compileError("unreachable");
477 log.debug("getGlobalSymbol '{s}'", .{name});505 log.debug("getGlobalSymbol '{s}'", .{name});
478 switch (base.tag) {506 switch (base.tag) {
479 // zig fmt: off507 // zig fmt: off
...@@ -495,6 +523,10 @@ pub const File = struct {...@@ -495,6 +523,10 @@ pub const File = struct {
495 const decl = module.declPtr(decl_index);523 const decl = module.declPtr(decl_index);
496 log.debug("updateDecl {*} ({s}), type={}", .{ decl, decl.name, decl.ty.fmtDebug() });524 log.debug("updateDecl {*} ({s}), type={}", .{ decl, decl.name, decl.ty.fmtDebug() });
497 assert(decl.has_tv);525 assert(decl.has_tv);
526 if (build_options.only_c) {
527 assert(base.tag == .c);
528 return @fieldParentPtr(C, "base", base).updateDecl(module, decl_index);
529 }
498 switch (base.tag) {530 switch (base.tag) {
499 // zig fmt: off531 // zig fmt: off
500 .coff => return @fieldParentPtr(Coff, "base", base).updateDecl(module, decl_index),532 .coff => return @fieldParentPtr(Coff, "base", base).updateDecl(module, decl_index),
...@@ -516,6 +548,10 @@ pub const File = struct {...@@ -516,6 +548,10 @@ pub const File = struct {
516 log.debug("updateFunc {*} ({s}), type={}", .{548 log.debug("updateFunc {*} ({s}), type={}", .{
517 owner_decl, owner_decl.name, owner_decl.ty.fmtDebug(),549 owner_decl, owner_decl.name, owner_decl.ty.fmtDebug(),
518 });550 });
551 if (build_options.only_c) {
552 assert(base.tag == .c);
553 return @fieldParentPtr(C, "base", base).updateFunc(module, func, air, liveness);
554 }
519 switch (base.tag) {555 switch (base.tag) {
520 // zig fmt: off556 // zig fmt: off
521 .coff => return @fieldParentPtr(Coff, "base", base).updateFunc(module, func, air, liveness),557 .coff => return @fieldParentPtr(Coff, "base", base).updateFunc(module, func, air, liveness),
...@@ -535,6 +571,10 @@ pub const File = struct {...@@ -535,6 +571,10 @@ pub const File = struct {
535 decl, decl.name, decl.src_line + 1,571 decl, decl.name, decl.src_line + 1,
536 });572 });
537 assert(decl.has_tv);573 assert(decl.has_tv);
574 if (build_options.only_c) {
575 assert(base.tag == .c);
576 return @fieldParentPtr(C, "base", base).updateDeclLineNumber(module, decl);
577 }
538 switch (base.tag) {578 switch (base.tag) {
539 .coff => return @fieldParentPtr(Coff, "base", base).updateDeclLineNumber(module, decl),579 .coff => return @fieldParentPtr(Coff, "base", base).updateDeclLineNumber(module, decl),
540 .elf => return @fieldParentPtr(Elf, "base", base).updateDeclLineNumber(module, decl),580 .elf => return @fieldParentPtr(Elf, "base", base).updateDeclLineNumber(module, decl),
...@@ -554,6 +594,10 @@ pub const File = struct {...@@ -554,6 +594,10 @@ pub const File = struct {
554 pub fn allocateDeclIndexes(base: *File, decl_index: Module.Decl.Index) error{OutOfMemory}!void {594 pub fn allocateDeclIndexes(base: *File, decl_index: Module.Decl.Index) error{OutOfMemory}!void {
555 const decl = base.options.module.?.declPtr(decl_index);595 const decl = base.options.module.?.declPtr(decl_index);
556 log.debug("allocateDeclIndexes {*} ({s})", .{ decl, decl.name });596 log.debug("allocateDeclIndexes {*} ({s})", .{ decl, decl.name });
597 if (build_options.only_c) {
598 assert(base.tag == .c);
599 return;
600 }
557 switch (base.tag) {601 switch (base.tag) {
558 .coff => return @fieldParentPtr(Coff, "base", base).allocateDeclIndexes(decl_index),602 .coff => return @fieldParentPtr(Coff, "base", base).allocateDeclIndexes(decl_index),
559 .elf => return @fieldParentPtr(Elf, "base", base).allocateDeclIndexes(decl_index),603 .elf => return @fieldParentPtr(Elf, "base", base).allocateDeclIndexes(decl_index),
...@@ -584,16 +628,19 @@ pub const File = struct {...@@ -584,16 +628,19 @@ pub const File = struct {
584 base.options.system_libs.deinit(base.allocator);628 base.options.system_libs.deinit(base.allocator);
585 switch (base.tag) {629 switch (base.tag) {
586 .coff => {630 .coff => {
631 if (build_options.only_c) unreachable;
587 const parent = @fieldParentPtr(Coff, "base", base);632 const parent = @fieldParentPtr(Coff, "base", base);
588 parent.deinit();633 parent.deinit();
589 base.allocator.destroy(parent);634 base.allocator.destroy(parent);
590 },635 },
591 .elf => {636 .elf => {
637 if (build_options.only_c) unreachable;
592 const parent = @fieldParentPtr(Elf, "base", base);638 const parent = @fieldParentPtr(Elf, "base", base);
593 parent.deinit();639 parent.deinit();
594 base.allocator.destroy(parent);640 base.allocator.destroy(parent);
595 },641 },
596 .macho => {642 .macho => {
643 if (build_options.only_c) unreachable;
597 const parent = @fieldParentPtr(MachO, "base", base);644 const parent = @fieldParentPtr(MachO, "base", base);
598 parent.deinit();645 parent.deinit();
599 base.allocator.destroy(parent);646 base.allocator.destroy(parent);
...@@ -604,21 +651,25 @@ pub const File = struct {...@@ -604,21 +651,25 @@ pub const File = struct {
604 base.allocator.destroy(parent);651 base.allocator.destroy(parent);
605 },652 },
606 .wasm => {653 .wasm => {
654 if (build_options.only_c) unreachable;
607 const parent = @fieldParentPtr(Wasm, "base", base);655 const parent = @fieldParentPtr(Wasm, "base", base);
608 parent.deinit();656 parent.deinit();
609 base.allocator.destroy(parent);657 base.allocator.destroy(parent);
610 },658 },
611 .spirv => {659 .spirv => {
660 if (build_options.only_c) unreachable;
612 const parent = @fieldParentPtr(SpirV, "base", base);661 const parent = @fieldParentPtr(SpirV, "base", base);
613 parent.deinit();662 parent.deinit();
614 base.allocator.destroy(parent);663 base.allocator.destroy(parent);
615 },664 },
616 .plan9 => {665 .plan9 => {
666 if (build_options.only_c) unreachable;
617 const parent = @fieldParentPtr(Plan9, "base", base);667 const parent = @fieldParentPtr(Plan9, "base", base);
618 parent.deinit();668 parent.deinit();
619 base.allocator.destroy(parent);669 base.allocator.destroy(parent);
620 },670 },
621 .nvptx => {671 .nvptx => {
672 if (build_options.only_c) unreachable;
622 const parent = @fieldParentPtr(NvPtx, "base", base);673 const parent = @fieldParentPtr(NvPtx, "base", base);
623 parent.deinit();674 parent.deinit();
624 base.allocator.destroy(parent);675 base.allocator.destroy(parent);
...@@ -629,6 +680,10 @@ pub const File = struct {...@@ -629,6 +680,10 @@ pub const File = struct {
629 /// Commit pending changes and write headers. Takes into account final output mode680 /// Commit pending changes and write headers. Takes into account final output mode
630 /// and `use_lld`, not only `effectiveOutputMode`.681 /// and `use_lld`, not only `effectiveOutputMode`.
631 pub fn flush(base: *File, comp: *Compilation, prog_node: *std.Progress.Node) !void {682 pub fn flush(base: *File, comp: *Compilation, prog_node: *std.Progress.Node) !void {
683 if (build_options.only_c) {
684 assert(base.tag == .c);
685 return @fieldParentPtr(C, "base", base).flush(comp, prog_node);
686 }
632 if (comp.clang_preprocessor_mode == .yes) {687 if (comp.clang_preprocessor_mode == .yes) {
633 const emit = base.options.emit orelse return; // -fno-emit-bin688 const emit = base.options.emit orelse return; // -fno-emit-bin
634 // TODO: avoid extra link step when it's just 1 object file (the `zig cc -c` case)689 // TODO: avoid extra link step when it's just 1 object file (the `zig cc -c` case)
...@@ -663,6 +718,10 @@ pub const File = struct {...@@ -663,6 +718,10 @@ pub const File = struct {
663 /// Commit pending changes and write headers. Works based on `effectiveOutputMode`718 /// Commit pending changes and write headers. Works based on `effectiveOutputMode`
664 /// rather than final output mode.719 /// rather than final output mode.
665 pub fn flushModule(base: *File, comp: *Compilation, prog_node: *std.Progress.Node) !void {720 pub fn flushModule(base: *File, comp: *Compilation, prog_node: *std.Progress.Node) !void {
721 if (build_options.only_c) {
722 assert(base.tag == .c);
723 return @fieldParentPtr(C, "base", base).flushModule(comp, prog_node);
724 }
666 switch (base.tag) {725 switch (base.tag) {
667 .coff => return @fieldParentPtr(Coff, "base", base).flushModule(comp, prog_node),726 .coff => return @fieldParentPtr(Coff, "base", base).flushModule(comp, prog_node),
668 .elf => return @fieldParentPtr(Elf, "base", base).flushModule(comp, prog_node),727 .elf => return @fieldParentPtr(Elf, "base", base).flushModule(comp, prog_node),
...@@ -677,6 +736,10 @@ pub const File = struct {...@@ -677,6 +736,10 @@ pub const File = struct {
677736
678 /// Called when a Decl is deleted from the Module.737 /// Called when a Decl is deleted from the Module.
679 pub fn freeDecl(base: *File, decl_index: Module.Decl.Index) void {738 pub fn freeDecl(base: *File, decl_index: Module.Decl.Index) void {
739 if (build_options.only_c) {
740 assert(base.tag == .c);
741 return @fieldParentPtr(C, "base", base).freeDecl(decl_index);
742 }
680 switch (base.tag) {743 switch (base.tag) {
681 .coff => @fieldParentPtr(Coff, "base", base).freeDecl(decl_index),744 .coff => @fieldParentPtr(Coff, "base", base).freeDecl(decl_index),
682 .elf => @fieldParentPtr(Elf, "base", base).freeDecl(decl_index),745 .elf => @fieldParentPtr(Elf, "base", base).freeDecl(decl_index),
...@@ -716,6 +779,10 @@ pub const File = struct {...@@ -716,6 +779,10 @@ pub const File = struct {
716 const decl = module.declPtr(decl_index);779 const decl = module.declPtr(decl_index);
717 log.debug("updateDeclExports {*} ({s})", .{ decl, decl.name });780 log.debug("updateDeclExports {*} ({s})", .{ decl, decl.name });
718 assert(decl.has_tv);781 assert(decl.has_tv);
782 if (build_options.only_c) {
783 assert(base.tag == .c);
784 return @fieldParentPtr(C, "base", base).updateDeclExports(module, decl_index, exports);
785 }
719 switch (base.tag) {786 switch (base.tag) {
720 .coff => return @fieldParentPtr(Coff, "base", base).updateDeclExports(module, decl_index, exports),787 .coff => return @fieldParentPtr(Coff, "base", base).updateDeclExports(module, decl_index, exports),
721 .elf => return @fieldParentPtr(Elf, "base", base).updateDeclExports(module, decl_index, exports),788 .elf => return @fieldParentPtr(Elf, "base", base).updateDeclExports(module, decl_index, exports),
...@@ -739,6 +806,7 @@ pub const File = struct {...@@ -739,6 +806,7 @@ pub const File = struct {
739 /// memory buffer, `offset`, so that it can make a note of potential relocation sites, should the806 /// memory buffer, `offset`, so that it can make a note of potential relocation sites, should the
740 /// `Decl`'s address was not yet resolved, or the containing atom gets moved in virtual memory.807 /// `Decl`'s address was not yet resolved, or the containing atom gets moved in virtual memory.
741 pub fn getDeclVAddr(base: *File, decl_index: Module.Decl.Index, reloc_info: RelocInfo) !u64 {808 pub fn getDeclVAddr(base: *File, decl_index: Module.Decl.Index, reloc_info: RelocInfo) !u64 {
809 if (build_options.only_c) unreachable;
742 switch (base.tag) {810 switch (base.tag) {
743 .coff => return @fieldParentPtr(Coff, "base", base).getDeclVAddr(decl_index, reloc_info),811 .coff => return @fieldParentPtr(Coff, "base", base).getDeclVAddr(decl_index, reloc_info),
744 .elf => return @fieldParentPtr(Elf, "base", base).getDeclVAddr(decl_index, reloc_info),812 .elf => return @fieldParentPtr(Elf, "base", base).getDeclVAddr(decl_index, reloc_info),