| author | |
| committer | |
| log | 2ef68631cb7045c277b348777b1a064845b95cd8 |
| tree | 00e1dca9b53a828a9926cf5b6d2a227dc939375a |
| parent | 333b12a8f9beb5864fa05ce413c5b935e925ec14 |
* move stage2.cpp code into zig0.cpp for simplicity
* add -ftime-report and some more CLI options to stage2
* stage2 compites the llvm cpu features string
* classifyFileExt understands more file extensions
* correction to generateBuiltinZigSource using the wrong allocator
(thanks dbandstra!)
* stage2 is now able to build hello.zig into hello.o using stage1 as a
library however it fails linking due to missing compiler-rt
* remove dead code
* simplify zig0 builtin.zig source
* fix not resolving builtin.zig source path causing duplicate imports
* fix stage1.h not being valid C code
* fix stage2.h not being valid C code17 files changed, 750 insertions(+), 678 deletions(-)
BRANCH_TODO+5-3| ... | ... | @@ -1,3 +1,6 @@ |
| 1 | * build & link against compiler-rt | |
| 2 | * build & link against freestanding libc | |
| 3 | * Cache integration for stage1 zig code compilation | |
| 1 | 4 | * `zig test` |
| 2 | 5 | * `zig build` |
| 3 | 6 | * `-ftime-report` |
| ... | ... | @@ -14,10 +17,7 @@ |
| 14 | 17 | - using it as a preprocessor (-E) |
| 15 | 18 | - try building some software |
| 16 | 19 | * support rpaths in ELF linker code |
| 17 | * build & link against compiler-rt | |
| 18 | - stage1 C++ code integration | |
| 19 | 20 | * repair @cImport |
| 20 | * build & link against freestanding libc | |
| 21 | 21 | * add CLI support for a way to pass extra flags to c source files |
| 22 | 22 | * capture lld stdout/stderr better |
| 23 | 23 | * musl |
| ... | ... | @@ -35,10 +35,12 @@ |
| 35 | 35 | * implement emit-h in stage2 |
| 36 | 36 | * implement -fno-emit-bin |
| 37 | 37 | * audit the base cache hash |
| 38 | * --main-pkg-path | |
| 38 | 39 | * audit the CLI options for stage2 |
| 39 | 40 | * `zig init-lib` |
| 40 | 41 | * `zig init-exe` |
| 41 | 42 | * `zig run` |
| 43 | * restore error messages for stage2_add_link_lib | |
| 42 | 44 | |
| 43 | 45 | * implement serialization/deserialization of incremental compilation metadata |
| 44 | 46 | * incremental compilation - implement detection of which source files changed |
CMakeLists.txt-1| ... | ... | @@ -258,7 +258,6 @@ find_package(Threads) |
| 258 | 258 | # This is our shim which will be replaced by stage1.zig. |
| 259 | 259 | set(ZIG0_SOURCES |
| 260 | 260 | "${CMAKE_SOURCE_DIR}/src/zig0.cpp" |
| 261 | "${CMAKE_SOURCE_DIR}/src/stage2.cpp" | |
| 262 | 261 | ) |
| 263 | 262 | |
| 264 | 263 | set(ZIG_SOURCES |
src-self-hosted/Compilation.zig+222-25| ... | ... | @@ -19,6 +19,7 @@ const libunwind = @import("libunwind.zig"); |
| 19 | 19 | const fatal = @import("main.zig").fatal; |
| 20 | 20 | const Module = @import("Module.zig"); |
| 21 | 21 | const Cache = @import("Cache.zig"); |
| 22 | const stage1 = @import("stage1.zig"); | |
| 22 | 23 | |
| 23 | 24 | /// General-purpose allocator. Used for both temporary and long-term storage. |
| 24 | 25 | gpa: *Allocator, |
| ... | ... | @@ -26,6 +27,7 @@ gpa: *Allocator, |
| 26 | 27 | arena_state: std.heap.ArenaAllocator.State, |
| 27 | 28 | bin_file: *link.File, |
| 28 | 29 | c_object_table: std.AutoArrayHashMapUnmanaged(*CObject, void) = .{}, |
| 30 | stage1_module: ?*stage1.Module, | |
| 29 | 31 | |
| 30 | 32 | link_error_flags: link.File.ErrorFlags = .{}, |
| 31 | 33 | |
| ... | ... | @@ -122,6 +124,8 @@ const Job = union(enum) { |
| 122 | 124 | |
| 123 | 125 | /// Generate builtin.zig source code and write it into the correct place. |
| 124 | 126 | generate_builtin_zig: void, |
| 127 | /// Use stage1 C++ code to compile zig code into an object file. | |
| 128 | stage1_module: void, | |
| 125 | 129 | }; |
| 126 | 130 | |
| 127 | 131 | pub const CObject = struct { |
| ... | ... | @@ -274,6 +278,7 @@ pub const InitOptions = struct { |
| 274 | 278 | strip: bool = false, |
| 275 | 279 | single_threaded: bool = false, |
| 276 | 280 | is_native_os: bool, |
| 281 | time_report: bool = false, | |
| 277 | 282 | link_eh_frame_hdr: bool = false, |
| 278 | 283 | linker_script: ?[]const u8 = null, |
| 279 | 284 | version_script: ?[]const u8 = null, |
| ... | ... | @@ -288,12 +293,20 @@ pub const InitOptions = struct { |
| 288 | 293 | clang_passthrough_mode: bool = false, |
| 289 | 294 | verbose_cc: bool = false, |
| 290 | 295 | verbose_link: bool = false, |
| 296 | verbose_tokenize: bool = false, | |
| 297 | verbose_ast: bool = false, | |
| 298 | verbose_ir: bool = false, | |
| 299 | verbose_llvm_ir: bool = false, | |
| 300 | verbose_cimport: bool = false, | |
| 301 | verbose_llvm_cpu_features: bool = false, | |
| 291 | 302 | is_test: bool = false, |
| 292 | 303 | stack_size_override: ?u64 = null, |
| 293 | 304 | self_exe_path: ?[]const u8 = null, |
| 294 | 305 | version: ?std.builtin.Version = null, |
| 295 | 306 | libc_installation: ?*const LibCInstallation = null, |
| 296 | 307 | machine_code_model: std.builtin.CodeModel = .default, |
| 308 | /// This is for stage1 and should be deleted upon completion of self-hosting. | |
| 309 | color: @import("main.zig").Color = .Auto, | |
| 297 | 310 | }; |
| 298 | 311 | |
| 299 | 312 | pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| ... | ... | @@ -332,11 +345,27 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 332 | 345 | { |
| 333 | 346 | break :blk true; |
| 334 | 347 | } |
| 348 | ||
| 349 | if (build_options.is_stage1) { | |
| 350 | // If stage1 generates an object file, self-hosted linker is not | |
| 351 | // yet sophisticated enough to handle that. | |
| 352 | break :blk options.root_pkg != null; | |
| 353 | } | |
| 354 | ||
| 335 | 355 | break :blk false; |
| 336 | 356 | }; |
| 337 | 357 | |
| 338 | 358 | // Make a decision on whether to use LLVM or our own backend. |
| 339 | 359 | const use_llvm = if (options.use_llvm) |explicit| explicit else blk: { |
| 360 | // If we have no zig code to compile, no need for LLVM. | |
| 361 | if (options.root_pkg == null) | |
| 362 | break :blk false; | |
| 363 | ||
| 364 | // If we are the stage1 compiler, we depend on the stage1 c++ llvm backend | |
| 365 | // to compile zig code. | |
| 366 | if (build_options.is_stage1) | |
| 367 | break :blk true; | |
| 368 | ||
| 340 | 369 | // We would want to prefer LLVM for release builds when it is available, however |
| 341 | 370 | // we don't have an LLVM backend yet :) |
| 342 | 371 | // We would also want to prefer LLVM for architectures that we don't have self-hosted support for too. |
| ... | ... | @@ -580,6 +609,118 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 580 | 609 | .ReleaseFast, .ReleaseSmall => false, |
| 581 | 610 | }; |
| 582 | 611 | |
| 612 | const llvm_cpu_features: ?[*:0]const u8 = if (build_options.have_llvm and use_llvm) blk: { | |
| 613 | var buf = std.ArrayList(u8).init(arena); | |
| 614 | for (options.target.cpu.arch.allFeaturesList()) |feature, index_usize| { | |
| 615 | const index = @intCast(Target.Cpu.Feature.Set.Index, index_usize); | |
| 616 | const is_enabled = options.target.cpu.features.isEnabled(index); | |
| 617 | ||
| 618 | if (feature.llvm_name) |llvm_name| { | |
| 619 | const plus_or_minus = "-+"[@boolToInt(is_enabled)]; | |
| 620 | try buf.ensureCapacity(buf.items.len + 2 + llvm_name.len); | |
| 621 | buf.appendAssumeCapacity(plus_or_minus); | |
| 622 | buf.appendSliceAssumeCapacity(llvm_name); | |
| 623 | buf.appendSliceAssumeCapacity(","); | |
| 624 | } | |
| 625 | } | |
| 626 | assert(mem.endsWith(u8, buf.items, ",")); | |
| 627 | buf.items[buf.items.len - 1] = 0; | |
| 628 | buf.shrink(buf.items.len); | |
| 629 | break :blk buf.items[0 .. buf.items.len - 1 :0].ptr; | |
| 630 | } else null; | |
| 631 | ||
| 632 | const stage1_module: ?*stage1.Module = if (build_options.is_stage1 and use_llvm) blk: { | |
| 633 | // Here we use the legacy stage1 C++ compiler to compile Zig code. | |
| 634 | const stage2_target = try arena.create(stage1.Stage2Target); | |
| 635 | stage2_target.* = .{ | |
| 636 | .arch = @enumToInt(options.target.cpu.arch) + 1, // skip over ZigLLVM_UnknownArch | |
| 637 | .os = @enumToInt(options.target.os.tag), | |
| 638 | .abi = @enumToInt(options.target.abi), | |
| 639 | .is_native_os = options.is_native_os, | |
| 640 | .is_native_cpu = false, // Only true when bootstrapping the compiler. | |
| 641 | .llvm_cpu_name = if (options.target.cpu.model.llvm_name) |s| s.ptr else null, | |
| 642 | .llvm_cpu_features = llvm_cpu_features.?, | |
| 643 | }; | |
| 644 | const progress = try arena.create(std.Progress); | |
| 645 | const main_progress_node = try progress.start("", 100); | |
| 646 | if (options.color == .Off) progress.terminal = null; | |
| 647 | ||
| 648 | const mod = module.?; | |
| 649 | const main_zig_file = mod.root_pkg.root_src_path; | |
| 650 | const zig_lib_dir = options.zig_lib_directory.path.?; | |
| 651 | const builtin_sub = &[_][]const u8{"builtin.zig"}; | |
| 652 | const builtin_zig_path = try mod.zig_cache_artifact_directory.join(arena, builtin_sub); | |
| 653 | ||
| 654 | const stage1_module = stage1.create( | |
| 655 | @enumToInt(options.optimize_mode), | |
| 656 | undefined, | |
| 657 | 0, // TODO --main-pkg-path | |
| 658 | main_zig_file.ptr, | |
| 659 | main_zig_file.len, | |
| 660 | zig_lib_dir.ptr, | |
| 661 | zig_lib_dir.len, | |
| 662 | stage2_target, | |
| 663 | options.is_test, | |
| 664 | ) orelse return error.OutOfMemory; | |
| 665 | ||
| 666 | const output_dir = bin_directory.path orelse "."; | |
| 667 | ||
| 668 | const stage1_pkg = try arena.create(stage1.Pkg); | |
| 669 | stage1_pkg.* = .{ | |
| 670 | .name_ptr = undefined, | |
| 671 | .name_len = 0, | |
| 672 | .path_ptr = undefined, | |
| 673 | .path_len = 0, | |
| 674 | .children_ptr = undefined, | |
| 675 | .children_len = 0, | |
| 676 | .parent = null, | |
| 677 | }; | |
| 678 | ||
| 679 | stage1_module.* = .{ | |
| 680 | .root_name_ptr = root_name.ptr, | |
| 681 | .root_name_len = root_name.len, | |
| 682 | .output_dir_ptr = output_dir.ptr, | |
| 683 | .output_dir_len = output_dir.len, | |
| 684 | .builtin_zig_path_ptr = builtin_zig_path.ptr, | |
| 685 | .builtin_zig_path_len = builtin_zig_path.len, | |
| 686 | .test_filter_ptr = "", | |
| 687 | .test_filter_len = 0, | |
| 688 | .test_name_prefix_ptr = "", | |
| 689 | .test_name_prefix_len = 0, | |
| 690 | .userdata = @ptrToInt(comp), | |
| 691 | .root_pkg = stage1_pkg, | |
| 692 | .code_model = @enumToInt(options.machine_code_model), | |
| 693 | .subsystem = stage1.TargetSubsystem.Auto, | |
| 694 | .err_color = @enumToInt(options.color), | |
| 695 | .pic = pic, | |
| 696 | .link_libc = options.link_libc, | |
| 697 | .link_libcpp = options.link_libcpp, | |
| 698 | .strip = options.strip, | |
| 699 | .is_single_threaded = single_threaded, | |
| 700 | .dll_export_fns = dll_export_fns, | |
| 701 | .link_mode_dynamic = link_mode == .Dynamic, | |
| 702 | .valgrind_enabled = valgrind, | |
| 703 | .function_sections = options.function_sections orelse false, | |
| 704 | .enable_stack_probing = stack_check, | |
| 705 | .enable_time_report = options.time_report, | |
| 706 | .enable_stack_report = false, | |
| 707 | .dump_analysis = false, | |
| 708 | .enable_doc_generation = false, | |
| 709 | .emit_bin = true, | |
| 710 | .emit_asm = false, | |
| 711 | .emit_llvm_ir = false, | |
| 712 | .test_is_evented = false, | |
| 713 | .verbose_tokenize = options.verbose_tokenize, | |
| 714 | .verbose_ast = options.verbose_ast, | |
| 715 | .verbose_ir = options.verbose_ir, | |
| 716 | .verbose_llvm_ir = options.verbose_llvm_ir, | |
| 717 | .verbose_cimport = options.verbose_cimport, | |
| 718 | .verbose_llvm_cpu_features = options.verbose_llvm_cpu_features, | |
| 719 | .main_progress_node = main_progress_node, | |
| 720 | }; | |
| 721 | break :blk stage1_module; | |
| 722 | } else null; | |
| 723 | ||
| 583 | 724 | const bin_file = try link.File.openPath(gpa, .{ |
| 584 | 725 | .directory = bin_directory, |
| 585 | 726 | .sub_path = emit_bin.basename, |
| ... | ... | @@ -626,6 +767,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 626 | 767 | .machine_code_model = options.machine_code_model, |
| 627 | 768 | .dll_export_fns = dll_export_fns, |
| 628 | 769 | .error_return_tracing = error_return_tracing, |
| 770 | .llvm_cpu_features = llvm_cpu_features, | |
| 629 | 771 | }); |
| 630 | 772 | errdefer bin_file.destroy(); |
| 631 | 773 | |
| ... | ... | @@ -635,6 +777,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 635 | 777 | .zig_lib_directory = options.zig_lib_directory, |
| 636 | 778 | .zig_cache_directory = options.zig_cache_directory, |
| 637 | 779 | .bin_file = bin_file, |
| 780 | .stage1_module = stage1_module, | |
| 638 | 781 | .work_queue = std.fifo.LinearFifo(Job, .Dynamic).init(gpa), |
| 639 | 782 | .keep_source_files_loaded = options.keep_source_files_loaded, |
| 640 | 783 | .use_clang = use_clang, |
| ... | ... | @@ -681,6 +824,10 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 681 | 824 | try comp.work_queue.writeItem(.{ .libunwind = {} }); |
| 682 | 825 | } |
| 683 | 826 | |
| 827 | if (comp.stage1_module) |module| { | |
| 828 | try comp.work_queue.writeItem(.{ .stage1_module = {} }); | |
| 829 | } | |
| 830 | ||
| 684 | 831 | return comp; |
| 685 | 832 | } |
| 686 | 833 | |
| ... | ... | @@ -689,6 +836,11 @@ pub fn destroy(self: *Compilation) void { |
| 689 | 836 | self.bin_file.destroy(); |
| 690 | 837 | if (optional_module) |module| module.deinit(); |
| 691 | 838 | |
| 839 | if (self.stage1_module) |module| { | |
| 840 | module.main_progress_node.?.end(); | |
| 841 | module.destroy(); | |
| 842 | } | |
| 843 | ||
| 692 | 844 | const gpa = self.gpa; |
| 693 | 845 | self.work_queue.deinit(); |
| 694 | 846 | |
| ... | ... | @@ -997,6 +1149,10 @@ pub fn performAllTheWork(self: *Compilation) error{OutOfMemory}!void { |
| 997 | 1149 | fatal("unable to update builtin.zig file: {}", .{@errorName(err)}); |
| 998 | 1150 | }; |
| 999 | 1151 | }, |
| 1152 | .stage1_module => { | |
| 1153 | // This Job is only queued up if there is a zig module. | |
| 1154 | self.stage1_module.?.build_object(); | |
| 1155 | }, | |
| 1000 | 1156 | }; |
| 1001 | 1157 | } |
| 1002 | 1158 | |
| ... | ... | @@ -1365,7 +1521,7 @@ pub fn addCCArgs( |
| 1365 | 1521 | try argv.append("-fPIC"); |
| 1366 | 1522 | } |
| 1367 | 1523 | }, |
| 1368 | .so, .assembly, .ll, .bc, .unknown => {}, | |
| 1524 | .shared_library, .assembly, .ll, .bc, .unknown, .static_library, .object, .zig, .zir => {}, | |
| 1369 | 1525 | } |
| 1370 | 1526 | if (out_dep_path) |p| { |
| 1371 | 1527 | try argv.appendSlice(&[_][]const u8{ "-MD", "-MV", "-MF", p }); |
| ... | ... | @@ -1445,17 +1601,39 @@ pub const FileExt = enum { |
| 1445 | 1601 | ll, |
| 1446 | 1602 | bc, |
| 1447 | 1603 | assembly, |
| 1448 | so, | |
| 1604 | shared_library, | |
| 1605 | object, | |
| 1606 | static_library, | |
| 1607 | zig, | |
| 1608 | zir, | |
| 1449 | 1609 | unknown, |
| 1450 | 1610 | |
| 1451 | 1611 | pub fn clangSupportsDepFile(ext: FileExt) bool { |
| 1452 | 1612 | return switch (ext) { |
| 1453 | 1613 | .c, .cpp, .h => true, |
| 1454 | .ll, .bc, .assembly, .so, .unknown => false, | |
| 1614 | ||
| 1615 | .ll, | |
| 1616 | .bc, | |
| 1617 | .assembly, | |
| 1618 | .shared_library, | |
| 1619 | .object, | |
| 1620 | .static_library, | |
| 1621 | .zig, | |
| 1622 | .zir, | |
| 1623 | .unknown, | |
| 1624 | => false, | |
| 1455 | 1625 | }; |
| 1456 | 1626 | } |
| 1457 | 1627 | }; |
| 1458 | 1628 | |
| 1629 | pub fn hasObjectExt(filename: []const u8) bool { | |
| 1630 | return mem.endsWith(u8, filename, ".o") or mem.endsWith(u8, filename, ".obj"); | |
| 1631 | } | |
| 1632 | ||
| 1633 | pub fn hasStaticLibraryExt(filename: []const u8) bool { | |
| 1634 | return mem.endsWith(u8, filename, ".a") or mem.endsWith(u8, filename, ".lib"); | |
| 1635 | } | |
| 1636 | ||
| 1459 | 1637 | pub fn hasCExt(filename: []const u8) bool { |
| 1460 | 1638 | return mem.endsWith(u8, filename, ".c"); |
| 1461 | 1639 | } |
| ... | ... | @@ -1471,6 +1649,32 @@ pub fn hasAsmExt(filename: []const u8) bool { |
| 1471 | 1649 | return mem.endsWith(u8, filename, ".s") or mem.endsWith(u8, filename, ".S"); |
| 1472 | 1650 | } |
| 1473 | 1651 | |
| 1652 | pub fn hasSharedLibraryExt(filename: []const u8) bool { | |
| 1653 | if (mem.endsWith(u8, filename, ".so") or | |
| 1654 | mem.endsWith(u8, filename, ".dll") or | |
| 1655 | mem.endsWith(u8, filename, ".dylib")) | |
| 1656 | { | |
| 1657 | return true; | |
| 1658 | } | |
| 1659 | // Look for .so.X, .so.X.Y, .so.X.Y.Z | |
| 1660 | var it = mem.split(filename, "."); | |
| 1661 | _ = it.next().?; | |
| 1662 | var so_txt = it.next() orelse return false; | |
| 1663 | while (!mem.eql(u8, so_txt, "so")) { | |
| 1664 | so_txt = it.next() orelse return false; | |
| 1665 | } | |
| 1666 | const n1 = it.next() orelse return false; | |
| 1667 | const n2 = it.next(); | |
| 1668 | const n3 = it.next(); | |
| 1669 | ||
| 1670 | _ = std.fmt.parseInt(u32, n1, 10) catch return false; | |
| 1671 | if (n2) |x| _ = std.fmt.parseInt(u32, x, 10) catch return false; | |
| 1672 | if (n3) |x| _ = std.fmt.parseInt(u32, x, 10) catch return false; | |
| 1673 | if (it.next() != null) return false; | |
| 1674 | ||
| 1675 | return true; | |
| 1676 | } | |
| 1677 | ||
| 1474 | 1678 | pub fn classifyFileExt(filename: []const u8) FileExt { |
| 1475 | 1679 | if (hasCExt(filename)) { |
| 1476 | 1680 | return .c; |
| ... | ... | @@ -1484,26 +1688,19 @@ pub fn classifyFileExt(filename: []const u8) FileExt { |
| 1484 | 1688 | return .assembly; |
| 1485 | 1689 | } else if (mem.endsWith(u8, filename, ".h")) { |
| 1486 | 1690 | return .h; |
| 1487 | } else if (mem.endsWith(u8, filename, ".so")) { | |
| 1488 | return .so; | |
| 1489 | } | |
| 1490 | // Look for .so.X, .so.X.Y, .so.X.Y.Z | |
| 1491 | var it = mem.split(filename, "."); | |
| 1492 | _ = it.next().?; | |
| 1493 | var so_txt = it.next() orelse return .unknown; | |
| 1494 | while (!mem.eql(u8, so_txt, "so")) { | |
| 1495 | so_txt = it.next() orelse return .unknown; | |
| 1691 | } else if (mem.endsWith(u8, filename, ".zig")) { | |
| 1692 | return .zig; | |
| 1693 | } else if (mem.endsWith(u8, filename, ".zir")) { | |
| 1694 | return .zig; | |
| 1695 | } else if (hasSharedLibraryExt(filename)) { | |
| 1696 | return .shared_library; | |
| 1697 | } else if (hasStaticLibraryExt(filename)) { | |
| 1698 | return .static_library; | |
| 1699 | } else if (hasObjectExt(filename)) { | |
| 1700 | return .object; | |
| 1701 | } else { | |
| 1702 | return .unknown; | |
| 1496 | 1703 | } |
| 1497 | const n1 = it.next() orelse return .unknown; | |
| 1498 | const n2 = it.next(); | |
| 1499 | const n3 = it.next(); | |
| 1500 | ||
| 1501 | _ = std.fmt.parseInt(u32, n1, 10) catch return .unknown; | |
| 1502 | if (n2) |x| _ = std.fmt.parseInt(u32, x, 10) catch return .unknown; | |
| 1503 | if (n3) |x| _ = std.fmt.parseInt(u32, x, 10) catch return .unknown; | |
| 1504 | if (it.next() != null) return .unknown; | |
| 1505 | ||
| 1506 | return .so; | |
| 1507 | 1704 | } |
| 1508 | 1705 | |
| 1509 | 1706 | test "classifyFileExt" { |
| ... | ... | @@ -1681,7 +1878,7 @@ pub fn dump_argv(argv: []const []const u8) void { |
| 1681 | 1878 | } |
| 1682 | 1879 | |
| 1683 | 1880 | pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) ![]u8 { |
| 1684 | var buffer = std.ArrayList(u8).init(comp.gpa); | |
| 1881 | var buffer = std.ArrayList(u8).init(allocator); | |
| 1685 | 1882 | defer buffer.deinit(); |
| 1686 | 1883 | |
| 1687 | 1884 | const target = comp.getTarget(); |
| ... | ... | @@ -1691,9 +1888,9 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) ![]u8 |
| 1691 | 1888 | try buffer.writer().print( |
| 1692 | 1889 | \\usingnamespace @import("std").builtin; |
| 1693 | 1890 | \\/// Deprecated |
| 1694 | \\pub const arch = std.Target.current.cpu.arch; | |
| 1891 | \\pub const arch = Target.current.cpu.arch; | |
| 1695 | 1892 | \\/// Deprecated |
| 1696 | \\pub const endian = std.Target.current.cpu.arch.endian(); | |
| 1893 | \\pub const endian = Target.current.cpu.arch.endian(); | |
| 1697 | 1894 | \\pub const output_mode = OutputMode.{}; |
| 1698 | 1895 | \\pub const link_mode = LinkMode.{}; |
| 1699 | 1896 | \\pub const is_test = {}; |
src-self-hosted/link.zig+13| ... | ... | @@ -69,6 +69,7 @@ pub const Options = struct { |
| 69 | 69 | linker_script: ?[]const u8 = null, |
| 70 | 70 | version_script: ?[]const u8 = null, |
| 71 | 71 | override_soname: ?[]const u8 = null, |
| 72 | llvm_cpu_features: ?[*:0]const u8 = null, | |
| 72 | 73 | /// Extra args passed directly to LLD. Ignored when not linking with LLD. |
| 73 | 74 | extra_lld_args: []const []const u8 = &[0][]const u8, |
| 74 | 75 | |
| ... | ... | @@ -134,6 +135,18 @@ pub const File = struct { |
| 134 | 135 | /// rewriting it. A malicious file is detected as incremental link failure |
| 135 | 136 | /// and does not cause Illegal Behavior. This operation is not atomic. |
| 136 | 137 | pub fn openPath(allocator: *Allocator, options: Options) !*File { |
| 138 | const use_stage1 = build_options.is_stage1 and options.use_llvm; | |
| 139 | if (use_stage1) { | |
| 140 | return switch (options.object_format) { | |
| 141 | .coff, .pe => &(try Coff.createEmpty(allocator, options)).base, | |
| 142 | .elf => &(try Elf.createEmpty(allocator, options)).base, | |
| 143 | .macho => &(try MachO.createEmpty(allocator, options)).base, | |
| 144 | .wasm => &(try Wasm.createEmpty(allocator, options)).base, | |
| 145 | .c => unreachable, // Reported error earlier. | |
| 146 | .hex => return error.HexObjectFormatUnimplemented, | |
| 147 | .raw => return error.RawObjectFormatUnimplemented, | |
| 148 | }; | |
| 149 | } | |
| 137 | 150 | const use_lld = build_options.have_llvm and options.use_lld; // comptime known false when !have_llvm |
| 138 | 151 | const sub_path = if (use_lld) blk: { |
| 139 | 152 | if (options.module == null) { |
src-self-hosted/link/Elf.zig+9-6| ... | ... | @@ -1222,13 +1222,16 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { |
| 1222 | 1222 | // If there is no Zig code to compile, then we should skip flushing the output file because it |
| 1223 | 1223 | // will not be part of the linker line anyway. |
| 1224 | 1224 | const module_obj_path: ?[]const u8 = if (self.base.options.module) |module| blk: { |
| 1225 | try self.flushModule(comp); | |
| 1225 | const use_stage1 = build_options.is_stage1 and self.base.options.use_llvm; | |
| 1226 | if (use_stage1) { | |
| 1227 | const obj_basename = try std.fmt.allocPrint(arena, "{}.o", .{self.base.options.root_name}); | |
| 1228 | const full_obj_path = try directory.join(arena, &[_][]const u8{obj_basename}); | |
| 1229 | break :blk full_obj_path; | |
| 1230 | } | |
| 1226 | 1231 | |
| 1232 | try self.flushModule(comp); | |
| 1227 | 1233 | const obj_basename = self.base.intermediary_basename.?; |
| 1228 | const full_obj_path = if (directory.path) |dir_path| | |
| 1229 | try std.fs.path.join(arena, &[_][]const u8{dir_path, obj_basename}) | |
| 1230 | else | |
| 1231 | obj_basename; | |
| 1234 | const full_obj_path = try directory.join(arena, &[_][]const u8{obj_basename}); | |
| 1232 | 1235 | break :blk full_obj_path; |
| 1233 | 1236 | } else null; |
| 1234 | 1237 | |
| ... | ... | @@ -1504,7 +1507,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { |
| 1504 | 1507 | // (the check for that needs to be earlier), but they could be full paths to .so files, in which |
| 1505 | 1508 | // case we want to avoid prepending "-l". |
| 1506 | 1509 | const ext = Compilation.classifyFileExt(link_lib); |
| 1507 | const arg = if (ext == .so) link_lib else try std.fmt.allocPrint(arena, "-l{}", .{link_lib}); | |
| 1510 | const arg = if (ext == .shared_library) link_lib else try std.fmt.allocPrint(arena, "-l{}", .{link_lib}); | |
| 1508 | 1511 | argv.appendAssumeCapacity(arg); |
| 1509 | 1512 | } |
| 1510 | 1513 |
src-self-hosted/main.zig+79-35| ... | ... | @@ -222,21 +222,27 @@ const usage_build_generic = |
| 222 | 222 | \\ --libc [file] Provide a file which specifies libc paths |
| 223 | 223 | \\ |
| 224 | 224 | \\Link Options: |
| 225 | \\ -l[lib], --library [lib] Link against system library | |
| 225 | \\ -l[lib], --library [lib] Link against system library | |
| 226 | 226 | \\ -L[d], --library-directory [d] Add a directory to the library search path |
| 227 | \\ -T[script] Use a custom linker script | |
| 228 | \\ --dynamic-linker [path] Set the dynamic interpreter path (usually ld.so) | |
| 229 | \\ --version [ver] Dynamic library semver | |
| 230 | \\ -rdynamic Add all symbols to the dynamic symbol table | |
| 231 | \\ -rpath [path] Add directory to the runtime library search path | |
| 232 | \\ --eh-frame-hdr Enable C++ exception handling by passing --eh-frame-hdr to linker | |
| 233 | \\ -dynamic Force output to be dynamically linked | |
| 234 | \\ -static Force output to be statically linked | |
| 227 | \\ -T[script] Use a custom linker script | |
| 228 | \\ --dynamic-linker [path] Set the dynamic interpreter path (usually ld.so) | |
| 229 | \\ --version [ver] Dynamic library semver | |
| 230 | \\ -rdynamic Add all symbols to the dynamic symbol table | |
| 231 | \\ -rpath [path] Add directory to the runtime library search path | |
| 232 | \\ --eh-frame-hdr Enable C++ exception handling by passing --eh-frame-hdr to linker | |
| 233 | \\ -dynamic Force output to be dynamically linked | |
| 234 | \\ -static Force output to be statically linked | |
| 235 | 235 | \\ |
| 236 | 236 | \\Debug Options (Zig Compiler Development): |
| 237 | \\ -ftime-report Print timing diagnostics | |
| 238 | \\ --verbose-link Display linker invocations | |
| 239 | \\ --verbose-cc Display C compiler invocations | |
| 237 | \\ -ftime-report Print timing diagnostics | |
| 238 | \\ --verbose-link Display linker invocations | |
| 239 | \\ --verbose-cc Display C compiler invocations | |
| 240 | \\ --verbose-tokenize Enable compiler debug output for tokenization | |
| 241 | \\ --verbose-ast Enable compiler debug output for AST parsing | |
| 242 | \\ --verbose-ir Enable compiler debug output for Zig IR | |
| 243 | \\ --verbose-llvm-ir Enable compiler debug output for LLVM IR | |
| 244 | \\ --verbose-cimport Enable compiler debug output for C imports | |
| 245 | \\ --verbose-llvm-cpu-features Enable compiler debug output for LLVM CPU features | |
| 240 | 246 | \\ |
| 241 | 247 | ; |
| 242 | 248 | |
| ... | ... | @@ -278,6 +284,12 @@ pub fn buildOutputType( |
| 278 | 284 | var watch = false; |
| 279 | 285 | var verbose_link = false; |
| 280 | 286 | var verbose_cc = false; |
| 287 | var verbose_tokenize = false; | |
| 288 | var verbose_ast = false; | |
| 289 | var verbose_ir = false; | |
| 290 | var verbose_llvm_ir = false; | |
| 291 | var verbose_cimport = false; | |
| 292 | var verbose_llvm_cpu_features = false; | |
| 281 | 293 | var time_report = false; |
| 282 | 294 | var show_builtin = false; |
| 283 | 295 | var emit_bin: Emit = .yes_default_path; |
| ... | ... | @@ -548,6 +560,18 @@ pub fn buildOutputType( |
| 548 | 560 | verbose_link = true; |
| 549 | 561 | } else if (mem.eql(u8, arg, "--verbose-cc")) { |
| 550 | 562 | verbose_cc = true; |
| 563 | } else if (mem.eql(u8, arg, "--verbose-tokenize")) { | |
| 564 | verbose_tokenize = true; | |
| 565 | } else if (mem.eql(u8, arg, "--verbose-ast")) { | |
| 566 | verbose_ast = true; | |
| 567 | } else if (mem.eql(u8, arg, "--verbose-ir")) { | |
| 568 | verbose_ir = true; | |
| 569 | } else if (mem.eql(u8, arg, "--verbose-llvm-ir")) { | |
| 570 | verbose_llvm_ir = true; | |
| 571 | } else if (mem.eql(u8, arg, "--verbose-cimport")) { | |
| 572 | verbose_cimport = true; | |
| 573 | } else if (mem.eql(u8, arg, "--verbose-llvm-cpu-features")) { | |
| 574 | verbose_llvm_cpu_features = true; | |
| 551 | 575 | } else if (mem.startsWith(u8, arg, "-T")) { |
| 552 | 576 | linker_script = arg[2..]; |
| 553 | 577 | } else if (mem.startsWith(u8, arg, "-L")) { |
| ... | ... | @@ -563,28 +587,27 @@ pub fn buildOutputType( |
| 563 | 587 | } else { |
| 564 | 588 | fatal("unrecognized parameter: '{}'", .{arg}); |
| 565 | 589 | } |
| 566 | } else if (mem.endsWith(u8, arg, ".o") or | |
| 567 | mem.endsWith(u8, arg, ".obj") or | |
| 568 | mem.endsWith(u8, arg, ".a") or | |
| 569 | mem.endsWith(u8, arg, ".lib")) | |
| 570 | { | |
| 571 | try link_objects.append(arg); | |
| 572 | } else if (Compilation.hasAsmExt(arg) or Compilation.hasCExt(arg) or Compilation.hasCppExt(arg)) { | |
| 573 | // TODO a way to pass extra flags on the CLI | |
| 574 | try c_source_files.append(.{ .src_path = arg }); | |
| 575 | } else if (mem.endsWith(u8, arg, ".so") or | |
| 576 | mem.endsWith(u8, arg, ".dylib") or | |
| 577 | mem.endsWith(u8, arg, ".dll")) | |
| 578 | { | |
| 579 | fatal("linking against dynamic libraries not yet supported", .{}); | |
| 580 | } else if (mem.endsWith(u8, arg, ".zig") or mem.endsWith(u8, arg, ".zir")) { | |
| 581 | if (root_src_file) |other| { | |
| 582 | fatal("found another zig file '{}' after root source file '{}'", .{ arg, other }); | |
| 583 | } else { | |
| 584 | root_src_file = arg; | |
| 585 | } | |
| 586 | } else { | |
| 587 | fatal("unrecognized file extension of parameter '{}'", .{arg}); | |
| 590 | } else switch (Compilation.classifyFileExt(arg)) { | |
| 591 | .object, .static_library => { | |
| 592 | try link_objects.append(arg); | |
| 593 | }, | |
| 594 | .assembly, .c, .cpp, .h, .ll, .bc => { | |
| 595 | // TODO a way to pass extra flags on the CLI | |
| 596 | try c_source_files.append(.{ .src_path = arg }); | |
| 597 | }, | |
| 598 | .shared_library => { | |
| 599 | fatal("linking against dynamic libraries not yet supported", .{}); | |
| 600 | }, | |
| 601 | .zig, .zir => { | |
| 602 | if (root_src_file) |other| { | |
| 603 | fatal("found another zig file '{}' after root source file '{}'", .{ arg, other }); | |
| 604 | } else { | |
| 605 | root_src_file = arg; | |
| 606 | } | |
| 607 | }, | |
| 608 | .unknown => { | |
| 609 | fatal("unrecognized file extension of parameter '{}'", .{arg}); | |
| 610 | }, | |
| 588 | 611 | } |
| 589 | 612 | } |
| 590 | 613 | } else { |
| ... | ... | @@ -617,7 +640,16 @@ pub fn buildOutputType( |
| 617 | 640 | const file_ext = Compilation.classifyFileExt(mem.spanZ(it.only_arg)); |
| 618 | 641 | switch (file_ext) { |
| 619 | 642 | .assembly, .c, .cpp, .ll, .bc, .h => try c_source_files.append(.{ .src_path = it.only_arg }), |
| 620 | .unknown, .so => try link_objects.append(it.only_arg), | |
| 643 | .unknown, .shared_library, .object, .static_library => { | |
| 644 | try link_objects.append(it.only_arg); | |
| 645 | }, | |
| 646 | .zig, .zir => { | |
| 647 | if (root_src_file) |other| { | |
| 648 | fatal("found another zig file '{}' after root source file '{}'", .{ it.only_arg, other }); | |
| 649 | } else { | |
| 650 | root_src_file = it.only_arg; | |
| 651 | } | |
| 652 | }, | |
| 621 | 653 | } |
| 622 | 654 | }, |
| 623 | 655 | .l => { |
| ... | ... | @@ -1173,7 +1205,15 @@ pub fn buildOutputType( |
| 1173 | 1205 | .libc_installation = if (libc_installation) |*lci| lci else null, |
| 1174 | 1206 | .verbose_cc = verbose_cc, |
| 1175 | 1207 | .verbose_link = verbose_link, |
| 1208 | .verbose_tokenize = verbose_tokenize, | |
| 1209 | .verbose_ast = verbose_ast, | |
| 1210 | .verbose_ir = verbose_ir, | |
| 1211 | .verbose_llvm_ir = verbose_llvm_ir, | |
| 1212 | .verbose_cimport = verbose_cimport, | |
| 1213 | .verbose_llvm_cpu_features = verbose_llvm_cpu_features, | |
| 1176 | 1214 | .machine_code_model = machine_code_model, |
| 1215 | .color = color, | |
| 1216 | .time_report = time_report, | |
| 1177 | 1217 | }) catch |err| { |
| 1178 | 1218 | fatal("unable to create compilation: {}", .{@errorName(err)}); |
| 1179 | 1219 | }; |
| ... | ... | @@ -1193,6 +1233,10 @@ pub fn buildOutputType( |
| 1193 | 1233 | fatal("TODO: implement `zig cc` when using it as a preprocessor", .{}); |
| 1194 | 1234 | } |
| 1195 | 1235 | |
| 1236 | if (build_options.is_stage1 and comp.stage1_module != null and watch) { | |
| 1237 | std.log.warn("--watch is not recommended with the stage1 backend; it leaks memory and is not capable of incremental compilation", .{}); | |
| 1238 | } | |
| 1239 | ||
| 1196 | 1240 | const stdin = std.io.getStdIn().inStream(); |
| 1197 | 1241 | const stderr = std.io.getStdErr().outStream(); |
| 1198 | 1242 | var repl_buf: [1024]u8 = undefined; |
src-self-hosted/stage1.zig+134-278| ... | ... | @@ -10,6 +10,7 @@ const stage2 = @import("main.zig"); |
| 10 | 10 | const fatal = stage2.fatal; |
| 11 | 11 | const CrossTarget = std.zig.CrossTarget; |
| 12 | 12 | const Target = std.Target; |
| 13 | const Compilation = @import("Compilation.zig"); | |
| 13 | 14 | |
| 14 | 15 | comptime { |
| 15 | 16 | assert(std.builtin.link_libc); |
| ... | ... | @@ -23,6 +24,8 @@ pub const log_level = stage2.log_level; |
| 23 | 24 | pub export fn main(argc: c_int, argv: [*]const [*:0]const u8) c_int { |
| 24 | 25 | std.debug.maybeEnableSegfaultHandler(); |
| 25 | 26 | |
| 27 | zig_stage1_os_init(); | |
| 28 | ||
| 26 | 29 | const gpa = std.heap.c_allocator; |
| 27 | 30 | var arena_instance = std.heap.ArenaAllocator.init(gpa); |
| 28 | 31 | defer arena_instance.deinit(); |
| ... | ... | @@ -36,6 +39,106 @@ pub export fn main(argc: c_int, argv: [*]const [*:0]const u8) c_int { |
| 36 | 39 | return 0; |
| 37 | 40 | } |
| 38 | 41 | |
| 42 | /// Matches stage2.Color; | |
| 43 | pub const ErrColor = c_int; | |
| 44 | /// Matches std.builtin.CodeModel | |
| 45 | pub const CodeModel = c_int; | |
| 46 | /// Matches std.Target.Os.Tag | |
| 47 | pub const OS = c_int; | |
| 48 | /// Matches std.builtin.BuildMode | |
| 49 | pub const BuildMode = c_int; | |
| 50 | ||
| 51 | pub const TargetSubsystem = extern enum(c_int) { | |
| 52 | Console, | |
| 53 | Windows, | |
| 54 | Posix, | |
| 55 | Native, | |
| 56 | EfiApplication, | |
| 57 | EfiBootServiceDriver, | |
| 58 | EfiRom, | |
| 59 | EfiRuntimeDriver, | |
| 60 | Auto, | |
| 61 | }; | |
| 62 | ||
| 63 | pub const Pkg = extern struct { | |
| 64 | name_ptr: [*]const u8, | |
| 65 | name_len: usize, | |
| 66 | path_ptr: [*]const u8, | |
| 67 | path_len: usize, | |
| 68 | children_ptr: [*]*Pkg, | |
| 69 | children_len: usize, | |
| 70 | parent: ?*Pkg, | |
| 71 | }; | |
| 72 | ||
| 73 | pub const Module = extern struct { | |
| 74 | root_name_ptr: [*]const u8, | |
| 75 | root_name_len: usize, | |
| 76 | output_dir_ptr: [*]const u8, | |
| 77 | output_dir_len: usize, | |
| 78 | builtin_zig_path_ptr: [*]const u8, | |
| 79 | builtin_zig_path_len: usize, | |
| 80 | test_filter_ptr: [*]const u8, | |
| 81 | test_filter_len: usize, | |
| 82 | test_name_prefix_ptr: [*]const u8, | |
| 83 | test_name_prefix_len: usize, | |
| 84 | userdata: usize, | |
| 85 | root_pkg: *Pkg, | |
| 86 | main_progress_node: ?*std.Progress.Node, | |
| 87 | code_model: CodeModel, | |
| 88 | subsystem: TargetSubsystem, | |
| 89 | err_color: ErrColor, | |
| 90 | pic: bool, | |
| 91 | link_libc: bool, | |
| 92 | link_libcpp: bool, | |
| 93 | strip: bool, | |
| 94 | is_single_threaded: bool, | |
| 95 | dll_export_fns: bool, | |
| 96 | link_mode_dynamic: bool, | |
| 97 | valgrind_enabled: bool, | |
| 98 | function_sections: bool, | |
| 99 | enable_stack_probing: bool, | |
| 100 | enable_time_report: bool, | |
| 101 | enable_stack_report: bool, | |
| 102 | dump_analysis: bool, | |
| 103 | enable_doc_generation: bool, | |
| 104 | emit_bin: bool, | |
| 105 | emit_asm: bool, | |
| 106 | emit_llvm_ir: bool, | |
| 107 | test_is_evented: bool, | |
| 108 | verbose_tokenize: bool, | |
| 109 | verbose_ast: bool, | |
| 110 | verbose_ir: bool, | |
| 111 | verbose_llvm_ir: bool, | |
| 112 | verbose_cimport: bool, | |
| 113 | verbose_llvm_cpu_features: bool, | |
| 114 | ||
| 115 | pub fn build_object(mod: *Module) void { | |
| 116 | zig_stage1_build_object(mod); | |
| 117 | } | |
| 118 | ||
| 119 | pub fn destroy(mod: *Module) void { | |
| 120 | zig_stage1_destroy(mod); | |
| 121 | } | |
| 122 | }; | |
| 123 | ||
| 124 | extern fn zig_stage1_os_init() void; | |
| 125 | ||
| 126 | pub const create = zig_stage1_create; | |
| 127 | extern fn zig_stage1_create( | |
| 128 | optimize_mode: BuildMode, | |
| 129 | main_pkg_path_ptr: [*]const u8, | |
| 130 | main_pkg_path_len: usize, | |
| 131 | root_src_path_ptr: [*]const u8, | |
| 132 | root_src_path_len: usize, | |
| 133 | zig_lib_dir_ptr: [*c]const u8, | |
| 134 | zig_lib_dir_len: usize, | |
| 135 | target: [*c]const Stage2Target, | |
| 136 | is_test_build: bool, | |
| 137 | ) ?*Module; | |
| 138 | ||
| 139 | extern fn zig_stage1_build_object(*Module) void; | |
| 140 | extern fn zig_stage1_destroy(*Module) void; | |
| 141 | ||
| 39 | 142 | // ABI warning |
| 40 | 143 | export fn stage2_panic(ptr: [*]const u8, len: usize) void { |
| 41 | 144 | @panic(ptr[0..len]); |
| ... | ... | @@ -199,297 +302,50 @@ export fn stage2_progress_update_node(node: *std.Progress.Node, done_count: usiz |
| 199 | 302 | } |
| 200 | 303 | |
| 201 | 304 | // ABI warning |
| 202 | const Stage2Target = extern struct { | |
| 305 | pub const Stage2Target = extern struct { | |
| 203 | 306 | arch: c_int, |
| 204 | vendor: c_int, | |
| 205 | ||
| 307 | os: OS, | |
| 206 | 308 | abi: c_int, |
| 207 | os: c_int, | |
| 208 | 309 | |
| 209 | 310 | is_native_os: bool, |
| 210 | 311 | is_native_cpu: bool, |
| 211 | 312 | |
| 212 | 313 | llvm_cpu_name: ?[*:0]const u8, |
| 213 | 314 | llvm_cpu_features: ?[*:0]const u8, |
| 214 | cpu_builtin_str: ?[*:0]const u8, | |
| 215 | os_builtin_str: ?[*:0]const u8, | |
| 216 | ||
| 217 | dynamic_linker: ?[*:0]const u8, | |
| 218 | ||
| 219 | llvm_cpu_features_asm_ptr: [*]const [*:0]const u8, | |
| 220 | llvm_cpu_features_asm_len: usize, | |
| 221 | ||
| 222 | fn fromTarget(self: *Stage2Target, cross_target: CrossTarget) !void { | |
| 223 | const allocator = std.heap.c_allocator; | |
| 224 | ||
| 225 | var dynamic_linker: ?[*:0]u8 = null; | |
| 226 | const target = try crossTargetToTarget(cross_target, &dynamic_linker); | |
| 227 | ||
| 228 | const generic_arch_name = target.cpu.arch.genericName(); | |
| 229 | var cpu_builtin_str_buffer = try std.ArrayListSentineled(u8, 0).allocPrint(allocator, | |
| 230 | \\Cpu{{ | |
| 231 | \\ .arch = .{}, | |
| 232 | \\ .model = &Target.{}.cpu.{}, | |
| 233 | \\ .features = Target.{}.featureSet(&[_]Target.{}.Feature{{ | |
| 234 | \\ | |
| 235 | , .{ | |
| 236 | @tagName(target.cpu.arch), | |
| 237 | generic_arch_name, | |
| 238 | target.cpu.model.name, | |
| 239 | generic_arch_name, | |
| 240 | generic_arch_name, | |
| 241 | }); | |
| 242 | defer cpu_builtin_str_buffer.deinit(); | |
| 243 | ||
| 244 | var llvm_features_buffer = try std.ArrayListSentineled(u8, 0).initSize(allocator, 0); | |
| 245 | defer llvm_features_buffer.deinit(); | |
| 246 | ||
| 247 | // Unfortunately we have to do the work twice, because Clang does not support | |
| 248 | // the same command line parameters for CPU features when assembling code as it does | |
| 249 | // when compiling C code. | |
| 250 | var asm_features_list = std.ArrayList([*:0]const u8).init(allocator); | |
| 251 | defer asm_features_list.deinit(); | |
| 252 | ||
| 253 | for (target.cpu.arch.allFeaturesList()) |feature, index_usize| { | |
| 254 | const index = @intCast(Target.Cpu.Feature.Set.Index, index_usize); | |
| 255 | const is_enabled = target.cpu.features.isEnabled(index); | |
| 256 | ||
| 257 | if (feature.llvm_name) |llvm_name| { | |
| 258 | const plus_or_minus = "-+"[@boolToInt(is_enabled)]; | |
| 259 | try llvm_features_buffer.append(plus_or_minus); | |
| 260 | try llvm_features_buffer.appendSlice(llvm_name); | |
| 261 | try llvm_features_buffer.appendSlice(","); | |
| 262 | } | |
| 263 | ||
| 264 | if (is_enabled) { | |
| 265 | // TODO some kind of "zig identifier escape" function rather than | |
| 266 | // unconditionally using @"" syntax | |
| 267 | try cpu_builtin_str_buffer.appendSlice(" .@\""); | |
| 268 | try cpu_builtin_str_buffer.appendSlice(feature.name); | |
| 269 | try cpu_builtin_str_buffer.appendSlice("\",\n"); | |
| 270 | } | |
| 271 | } | |
| 272 | ||
| 273 | switch (target.cpu.arch) { | |
| 274 | .riscv32, .riscv64 => { | |
| 275 | if (Target.riscv.featureSetHas(target.cpu.features, .relax)) { | |
| 276 | try asm_features_list.append("-mrelax"); | |
| 277 | } else { | |
| 278 | try asm_features_list.append("-mno-relax"); | |
| 279 | } | |
| 280 | }, | |
| 281 | else => { | |
| 282 | // TODO | |
| 283 | // Argh, why doesn't the assembler accept the list of CPU features?! | |
| 284 | // I don't see a way to do this other than hard coding everything. | |
| 285 | }, | |
| 286 | } | |
| 287 | ||
| 288 | try cpu_builtin_str_buffer.appendSlice( | |
| 289 | \\ }), | |
| 290 | \\}; | |
| 291 | \\ | |
| 292 | ); | |
| 293 | ||
| 294 | assert(mem.endsWith(u8, llvm_features_buffer.span(), ",")); | |
| 295 | llvm_features_buffer.shrink(llvm_features_buffer.len() - 1); | |
| 296 | ||
| 297 | var os_builtin_str_buffer = try std.ArrayListSentineled(u8, 0).allocPrint(allocator, | |
| 298 | \\Os{{ | |
| 299 | \\ .tag = .{}, | |
| 300 | \\ .version_range = .{{ | |
| 301 | , .{@tagName(target.os.tag)}); | |
| 302 | defer os_builtin_str_buffer.deinit(); | |
| 303 | ||
| 304 | // We'll re-use the OS version range builtin string for the cache hash. | |
| 305 | const os_builtin_str_ver_start_index = os_builtin_str_buffer.len(); | |
| 306 | ||
| 307 | @setEvalBranchQuota(2000); | |
| 308 | switch (target.os.tag) { | |
| 309 | .freestanding, | |
| 310 | .ananas, | |
| 311 | .cloudabi, | |
| 312 | .dragonfly, | |
| 313 | .fuchsia, | |
| 314 | .ios, | |
| 315 | .kfreebsd, | |
| 316 | .lv2, | |
| 317 | .solaris, | |
| 318 | .haiku, | |
| 319 | .minix, | |
| 320 | .rtems, | |
| 321 | .nacl, | |
| 322 | .cnk, | |
| 323 | .aix, | |
| 324 | .cuda, | |
| 325 | .nvcl, | |
| 326 | .amdhsa, | |
| 327 | .ps4, | |
| 328 | .elfiamcu, | |
| 329 | .tvos, | |
| 330 | .watchos, | |
| 331 | .mesa3d, | |
| 332 | .contiki, | |
| 333 | .amdpal, | |
| 334 | .hermit, | |
| 335 | .hurd, | |
| 336 | .wasi, | |
| 337 | .emscripten, | |
| 338 | .uefi, | |
| 339 | .other, | |
| 340 | => try os_builtin_str_buffer.appendSlice(" .none = {} }\n"), | |
| 341 | ||
| 342 | .freebsd, | |
| 343 | .macosx, | |
| 344 | .netbsd, | |
| 345 | .openbsd, | |
| 346 | => try os_builtin_str_buffer.outStream().print( | |
| 347 | \\ .semver = .{{ | |
| 348 | \\ .min = .{{ | |
| 349 | \\ .major = {}, | |
| 350 | \\ .minor = {}, | |
| 351 | \\ .patch = {}, | |
| 352 | \\ }}, | |
| 353 | \\ .max = .{{ | |
| 354 | \\ .major = {}, | |
| 355 | \\ .minor = {}, | |
| 356 | \\ .patch = {}, | |
| 357 | \\ }}, | |
| 358 | \\ }}}}, | |
| 359 | \\ | |
| 360 | , .{ | |
| 361 | target.os.version_range.semver.min.major, | |
| 362 | target.os.version_range.semver.min.minor, | |
| 363 | target.os.version_range.semver.min.patch, | |
| 364 | ||
| 365 | target.os.version_range.semver.max.major, | |
| 366 | target.os.version_range.semver.max.minor, | |
| 367 | target.os.version_range.semver.max.patch, | |
| 368 | }), | |
| 369 | ||
| 370 | .linux => try os_builtin_str_buffer.outStream().print( | |
| 371 | \\ .linux = .{{ | |
| 372 | \\ .range = .{{ | |
| 373 | \\ .min = .{{ | |
| 374 | \\ .major = {}, | |
| 375 | \\ .minor = {}, | |
| 376 | \\ .patch = {}, | |
| 377 | \\ }}, | |
| 378 | \\ .max = .{{ | |
| 379 | \\ .major = {}, | |
| 380 | \\ .minor = {}, | |
| 381 | \\ .patch = {}, | |
| 382 | \\ }}, | |
| 383 | \\ }}, | |
| 384 | \\ .glibc = .{{ | |
| 385 | \\ .major = {}, | |
| 386 | \\ .minor = {}, | |
| 387 | \\ .patch = {}, | |
| 388 | \\ }}, | |
| 389 | \\ }}}}, | |
| 390 | \\ | |
| 391 | , .{ | |
| 392 | target.os.version_range.linux.range.min.major, | |
| 393 | target.os.version_range.linux.range.min.minor, | |
| 394 | target.os.version_range.linux.range.min.patch, | |
| 395 | ||
| 396 | target.os.version_range.linux.range.max.major, | |
| 397 | target.os.version_range.linux.range.max.minor, | |
| 398 | target.os.version_range.linux.range.max.patch, | |
| 399 | ||
| 400 | target.os.version_range.linux.glibc.major, | |
| 401 | target.os.version_range.linux.glibc.minor, | |
| 402 | target.os.version_range.linux.glibc.patch, | |
| 403 | }), | |
| 404 | ||
| 405 | .windows => try os_builtin_str_buffer.outStream().print( | |
| 406 | \\ .windows = .{{ | |
| 407 | \\ .min = {s}, | |
| 408 | \\ .max = {s}, | |
| 409 | \\ }}}}, | |
| 410 | \\ | |
| 411 | , .{ | |
| 412 | target.os.version_range.windows.min, | |
| 413 | target.os.version_range.windows.max, | |
| 414 | }), | |
| 415 | } | |
| 416 | try os_builtin_str_buffer.appendSlice("};\n"); | |
| 417 | ||
| 418 | const glibc_or_darwin_version = blk: { | |
| 419 | if (target.isGnuLibC()) { | |
| 420 | const stage1_glibc = try std.heap.c_allocator.create(Stage2SemVer); | |
| 421 | const stage2_glibc = target.os.version_range.linux.glibc; | |
| 422 | stage1_glibc.* = .{ | |
| 423 | .major = stage2_glibc.major, | |
| 424 | .minor = stage2_glibc.minor, | |
| 425 | .patch = stage2_glibc.patch, | |
| 426 | }; | |
| 427 | break :blk stage1_glibc; | |
| 428 | } else if (target.isDarwin()) { | |
| 429 | const stage1_semver = try std.heap.c_allocator.create(Stage2SemVer); | |
| 430 | const stage2_semver = target.os.version_range.semver.min; | |
| 431 | stage1_semver.* = .{ | |
| 432 | .major = stage2_semver.major, | |
| 433 | .minor = stage2_semver.minor, | |
| 434 | .patch = stage2_semver.patch, | |
| 435 | }; | |
| 436 | break :blk stage1_semver; | |
| 437 | } else { | |
| 438 | break :blk null; | |
| 439 | } | |
| 440 | }; | |
| 441 | ||
| 442 | const std_dl = target.standardDynamicLinkerPath(); | |
| 443 | const std_dl_z = if (std_dl.get()) |dl| | |
| 444 | (try mem.dupeZ(std.heap.c_allocator, u8, dl)).ptr | |
| 445 | else | |
| 446 | null; | |
| 447 | ||
| 448 | const asm_features = asm_features_list.toOwnedSlice(); | |
| 449 | self.* = .{ | |
| 450 | .arch = @enumToInt(target.cpu.arch) + 1, // skip over ZigLLVM_UnknownArch | |
| 451 | .vendor = 0, | |
| 452 | .os = @enumToInt(target.os.tag), | |
| 453 | .abi = @enumToInt(target.abi), | |
| 454 | .llvm_cpu_name = if (target.cpu.model.llvm_name) |s| s.ptr else null, | |
| 455 | .llvm_cpu_features = llvm_features_buffer.toOwnedSlice().ptr, | |
| 456 | .llvm_cpu_features_asm_ptr = asm_features.ptr, | |
| 457 | .llvm_cpu_features_asm_len = asm_features.len, | |
| 458 | .cpu_builtin_str = cpu_builtin_str_buffer.toOwnedSlice().ptr, | |
| 459 | .os_builtin_str = os_builtin_str_buffer.toOwnedSlice().ptr, | |
| 460 | .is_native_os = cross_target.isNativeOs(), | |
| 461 | .is_native_cpu = cross_target.isNativeCpu(), | |
| 462 | .glibc_or_darwin_version = glibc_or_darwin_version, | |
| 463 | .dynamic_linker = dynamic_linker, | |
| 464 | .standard_dynamic_linker_path = std_dl_z, | |
| 465 | }; | |
| 466 | } | |
| 467 | 315 | }; |
| 468 | 316 | |
| 469 | fn crossTargetToTarget(cross_target: CrossTarget, dynamic_linker_ptr: *?[*:0]u8) !Target { | |
| 470 | var info = try std.zig.system.NativeTargetInfo.detect(std.heap.c_allocator, cross_target); | |
| 471 | if (info.cpu_detection_unimplemented) { | |
| 472 | // TODO We want to just use detected_info.target but implementing | |
| 473 | // CPU model & feature detection is todo so here we rely on LLVM. | |
| 474 | const llvm = @import("llvm.zig"); | |
| 475 | const llvm_cpu_name = llvm.GetHostCPUName(); | |
| 476 | const llvm_cpu_features = llvm.GetNativeFeatures(); | |
| 477 | const arch = Target.current.cpu.arch; | |
| 478 | info.target.cpu = try detectNativeCpuWithLLVM(arch, llvm_cpu_name, llvm_cpu_features); | |
| 479 | cross_target.updateCpuFeatures(&info.target.cpu.features); | |
| 480 | info.target.cpu.arch = cross_target.getCpuArch(); | |
| 481 | } | |
| 482 | if (info.dynamic_linker.get()) |dl| { | |
| 483 | dynamic_linker_ptr.* = try mem.dupeZ(std.heap.c_allocator, u8, dl); | |
| 484 | } else { | |
| 485 | dynamic_linker_ptr.* = null; | |
| 486 | } | |
| 487 | return info.target; | |
| 488 | } | |
| 489 | ||
| 490 | 317 | // ABI warning |
| 491 | 318 | const Stage2SemVer = extern struct { |
| 492 | 319 | major: u32, |
| 493 | 320 | minor: u32, |
| 494 | 321 | patch: u32, |
| 495 | 322 | }; |
| 323 | ||
| 324 | // ABI warning | |
| 325 | export fn stage2_cimport(stage1: *Module) [*:0]const u8 { | |
| 326 | @panic("TODO implement stage2_cimport"); | |
| 327 | } | |
| 328 | ||
| 329 | export fn stage2_add_link_lib( | |
| 330 | stage1: *Module, | |
| 331 | lib_name_ptr: [*c]const u8, | |
| 332 | lib_name_len: usize, | |
| 333 | symbol_name_ptr: [*c]const u8, | |
| 334 | symbol_name_len: usize, | |
| 335 | ) ?[*:0]const u8 { | |
| 336 | return null; // no error | |
| 337 | } | |
| 338 | ||
| 339 | export fn stage2_fetch_file( | |
| 340 | stage1: *Module, | |
| 341 | path_ptr: [*]const u8, | |
| 342 | path_len: usize, | |
| 343 | result_len: *usize, | |
| 344 | ) ?[*]const u8 { | |
| 345 | const comp = @intToPtr(*Compilation, stage1.userdata); | |
| 346 | // TODO integrate this with cache hash | |
| 347 | const file_path = path_ptr[0..path_len]; | |
| 348 | const contents = std.fs.cwd().readFileAlloc(comp.gpa, file_path, std.math.maxInt(u32)) catch return null; | |
| 349 | result_len.* = contents.len; | |
| 350 | return contents.ptr; | |
| 351 | } |
src/analyze.cpp+1-1| ... | ... | @@ -7987,7 +7987,7 @@ Error file_fetch(CodeGen *g, Buf *resolved_path, Buf *contents_buf) { |
| 7987 | 7987 | size_t len; |
| 7988 | 7988 | const char *contents = stage2_fetch_file(&g->stage1, buf_ptr(resolved_path), buf_len(resolved_path), &len); |
| 7989 | 7989 | if (contents == nullptr) |
| 7990 | return ErrorNoMem; | |
| 7990 | return ErrorFileNotFound; | |
| 7991 | 7991 | buf_init_from_mem(contents_buf, contents, len); |
| 7992 | 7992 | return ErrorNone; |
| 7993 | 7993 | } |
src/codegen.cpp+26-35| ... | ... | @@ -8809,33 +8809,18 @@ Buf *codegen_generate_builtin_source(CodeGen *g) { |
| 8809 | 8809 | static_assert(TargetSubsystemEfiBootServiceDriver == 5, ""); |
| 8810 | 8810 | static_assert(TargetSubsystemEfiRom == 6, ""); |
| 8811 | 8811 | static_assert(TargetSubsystemEfiRuntimeDriver == 7, ""); |
| 8812 | { | |
| 8813 | const char *endian_str = g->is_big_endian ? "Endian.Big" : "Endian.Little"; | |
| 8814 | buf_appendf(contents, "pub const endian = %s;\n", endian_str); | |
| 8815 | } | |
| 8812 | ||
| 8813 | buf_append_str(contents, "/// Deprecated: use `std.Target.current.cpu.arch`\n"); | |
| 8814 | buf_append_str(contents, "pub const arch = Target.current.cpu.arch;\n"); | |
| 8815 | buf_append_str(contents, "/// Deprecated: use `std.Target.current.cpu.arch.endian()`\n"); | |
| 8816 | buf_append_str(contents, "pub const endian = Target.current.cpu.arch.endian();\n"); | |
| 8816 | 8817 | buf_appendf(contents, "pub const output_mode = OutputMode.Obj;\n"); |
| 8817 | 8818 | buf_appendf(contents, "pub const link_mode = LinkMode.Static;\n"); |
| 8818 | 8819 | buf_appendf(contents, "pub const is_test = false;\n"); |
| 8819 | 8820 | buf_appendf(contents, "pub const single_threaded = %s;\n", bool_to_str(g->is_single_threaded)); |
| 8820 | buf_append_str(contents, "/// Deprecated: use `std.Target.cpu.arch`\n"); | |
| 8821 | buf_appendf(contents, "pub const arch = Arch.%s;\n", cur_arch); | |
| 8822 | 8821 | buf_appendf(contents, "pub const abi = Abi.%s;\n", cur_abi); |
| 8823 | { | |
| 8824 | buf_append_str(contents, "pub const cpu: Cpu = "); | |
| 8825 | if (g->zig_target->cpu_builtin_str != nullptr) { | |
| 8826 | buf_append_str(contents, g->zig_target->cpu_builtin_str); | |
| 8827 | } else { | |
| 8828 | buf_appendf(contents, "Target.Cpu.baseline(.%s);\n", cur_arch); | |
| 8829 | } | |
| 8830 | } | |
| 8831 | { | |
| 8832 | buf_append_str(contents, "pub const os = "); | |
| 8833 | if (g->zig_target->os_builtin_str != nullptr) { | |
| 8834 | buf_append_str(contents, g->zig_target->os_builtin_str); | |
| 8835 | } else { | |
| 8836 | buf_appendf(contents, "Target.Os.Tag.defaultVersionRange(.%s);\n", cur_os); | |
| 8837 | } | |
| 8838 | } | |
| 8822 | buf_appendf(contents, "pub const cpu: Cpu = Target.Cpu.baseline(.%s);\n", cur_arch); | |
| 8823 | buf_appendf(contents, "pub const os = Target.Os.Tag.defaultVersionRange(.%s);\n", cur_os); | |
| 8839 | 8824 | buf_appendf(contents, "pub const object_format = ObjectFormat.%s;\n", cur_obj_fmt); |
| 8840 | 8825 | buf_appendf(contents, "pub const mode = %s;\n", build_mode_to_str(g->build_mode)); |
| 8841 | 8826 | buf_appendf(contents, "pub const link_libc = %s;\n", bool_to_str(g->link_libc)); |
| ... | ... | @@ -8866,6 +8851,8 @@ static Error define_builtin_compile_vars(CodeGen *g) { |
| 8866 | 8851 | if (g->std_package == nullptr) |
| 8867 | 8852 | return ErrorNone; |
| 8868 | 8853 | |
| 8854 | assert(g->main_pkg); | |
| 8855 | ||
| 8869 | 8856 | const char *builtin_zig_basename = "builtin.zig"; |
| 8870 | 8857 | |
| 8871 | 8858 | Buf *contents; |
| ... | ... | @@ -8879,17 +8866,22 @@ static Error define_builtin_compile_vars(CodeGen *g) { |
| 8879 | 8866 | fprintf(stderr, "Unable to write file '%s': %s\n", buf_ptr(g->builtin_zig_path), err_str(err)); |
| 8880 | 8867 | exit(1); |
| 8881 | 8868 | } |
| 8869 | ||
| 8870 | g->compile_var_package = new_package(buf_ptr(g->output_dir), builtin_zig_basename, "builtin"); | |
| 8882 | 8871 | } else { |
| 8872 | Buf *resolve_paths[] = { g->builtin_zig_path, }; | |
| 8873 | *g->builtin_zig_path = os_path_resolve(resolve_paths, 1); | |
| 8874 | ||
| 8883 | 8875 | contents = buf_alloc(); |
| 8884 | 8876 | if ((err = os_fetch_file_path(g->builtin_zig_path, contents))) { |
| 8885 | 8877 | fprintf(stderr, "unable to open '%s': %s\n", buf_ptr(g->builtin_zig_path), err_str(err)); |
| 8886 | 8878 | exit(1); |
| 8887 | 8879 | } |
| 8880 | Buf builtin_dirname = BUF_INIT; | |
| 8881 | os_path_dirname(g->builtin_zig_path, &builtin_dirname); | |
| 8882 | g->compile_var_package = new_package(buf_ptr(&builtin_dirname), builtin_zig_basename, "builtin"); | |
| 8888 | 8883 | } |
| 8889 | 8884 | |
| 8890 | assert(g->main_pkg); | |
| 8891 | assert(g->std_package); | |
| 8892 | g->compile_var_package = new_package(buf_ptr(g->output_dir), builtin_zig_basename, "builtin"); | |
| 8893 | 8885 | if (g->is_test_build) { |
| 8894 | 8886 | if (g->test_runner_package == nullptr) { |
| 8895 | 8887 | g->test_runner_package = create_test_runner_pkg(g); |
| ... | ... | @@ -8914,6 +8906,13 @@ static void init(CodeGen *g) { |
| 8914 | 8906 | if (g->module) |
| 8915 | 8907 | return; |
| 8916 | 8908 | |
| 8909 | codegen_add_time_event(g, "Initialize"); | |
| 8910 | { | |
| 8911 | const char *progress_name = "Initialize"; | |
| 8912 | codegen_switch_sub_prog_node(g, stage2_progress_start(g->main_progress_node, | |
| 8913 | progress_name, strlen(progress_name), 0)); | |
| 8914 | } | |
| 8915 | ||
| 8917 | 8916 | g->have_err_ret_tracing = detect_err_ret_tracing(g); |
| 8918 | 8917 | |
| 8919 | 8918 | assert(g->root_out_name); |
| ... | ... | @@ -9374,19 +9373,11 @@ void codegen_destroy(CodeGen *g) { |
| 9374 | 9373 | |
| 9375 | 9374 | CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget *target, |
| 9376 | 9375 | BuildMode build_mode, Buf *override_lib_dir, |
| 9377 | bool is_test_build, Stage2ProgressNode *progress_node) | |
| 9376 | bool is_test_build) | |
| 9378 | 9377 | { |
| 9379 | 9378 | CodeGen *g = heap::c_allocator.create<CodeGen>(); |
| 9380 | 9379 | g->emit_bin = true; |
| 9381 | 9380 | g->pass1_arena = heap::ArenaAllocator::construct(&heap::c_allocator, &heap::c_allocator, "pass1"); |
| 9382 | g->main_progress_node = progress_node; | |
| 9383 | ||
| 9384 | codegen_add_time_event(g, "Initialize"); | |
| 9385 | { | |
| 9386 | const char *progress_name = "Initialize"; | |
| 9387 | codegen_switch_sub_prog_node(g, stage2_progress_start(g->main_progress_node, | |
| 9388 | progress_name, strlen(progress_name), 0)); | |
| 9389 | } | |
| 9390 | 9381 | |
| 9391 | 9382 | g->subsystem = TargetSubsystemAuto; |
| 9392 | 9383 | g->zig_target = target; |
| ... | ... | @@ -9440,7 +9431,7 @@ CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget |
| 9440 | 9431 | Buf resolved_main_pkg_path = os_path_resolve(&main_pkg_path, 1); |
| 9441 | 9432 | |
| 9442 | 9433 | if (!buf_starts_with_buf(&resolved_root_src_path, &resolved_main_pkg_path)) { |
| 9443 | fprintf(stderr, "Root source path '%s' outside main package path '%s'", | |
| 9434 | fprintf(stderr, "Root source path '%s' outside main package path '%s'\n", | |
| 9444 | 9435 | buf_ptr(root_src_path), buf_ptr(main_pkg_path)); |
| 9445 | 9436 | exit(1); |
| 9446 | 9437 | } |
src/codegen.hpp+1-2| ... | ... | @@ -16,8 +16,7 @@ |
| 16 | 16 | #include <stdio.h> |
| 17 | 17 | |
| 18 | 18 | CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget *target, |
| 19 | BuildMode build_mode, Buf *zig_lib_dir, | |
| 20 | bool is_test_build, Stage2ProgressNode *progress_node); | |
| 19 | BuildMode build_mode, Buf *zig_lib_dir, bool is_test_build); | |
| 21 | 20 | |
| 22 | 21 | void codegen_build_object(CodeGen *g); |
| 23 | 22 | void codegen_destroy(CodeGen *); |
src/stage1.cpp+6-5| ... | ... | @@ -20,13 +20,14 @@ struct ZigStage1 *zig_stage1_create(BuildMode optimize_mode, |
| 20 | 20 | const char *main_pkg_path_ptr, size_t main_pkg_path_len, |
| 21 | 21 | const char *root_src_path_ptr, size_t root_src_path_len, |
| 22 | 22 | const char *zig_lib_dir_ptr, size_t zig_lib_dir_len, |
| 23 | const ZigTarget *target, bool is_test_build, Stage2ProgressNode *progress_node) | |
| 23 | const ZigTarget *target, bool is_test_build) | |
| 24 | 24 | { |
| 25 | Buf *main_pkg_path = buf_create_from_mem(main_pkg_path_ptr, main_pkg_path_len); | |
| 25 | Buf *main_pkg_path = (main_pkg_path_len == 0) ? | |
| 26 | nullptr : buf_create_from_mem(main_pkg_path_ptr, main_pkg_path_len); | |
| 26 | 27 | Buf *root_src_path = buf_create_from_mem(root_src_path_ptr, root_src_path_len); |
| 27 | 28 | Buf *zig_lib_dir = buf_create_from_mem(zig_lib_dir_ptr, zig_lib_dir_len); |
| 28 | 29 | CodeGen *g = codegen_create(main_pkg_path, root_src_path, target, optimize_mode, |
| 29 | zig_lib_dir, is_test_build, progress_node); | |
| 30 | zig_lib_dir, is_test_build); | |
| 30 | 31 | return &g->stage1; |
| 31 | 32 | } |
| 32 | 33 | |
| ... | ... | @@ -68,8 +69,6 @@ void zig_stage1_build_object(struct ZigStage1 *stage1) { |
| 68 | 69 | CodeGen *g = reinterpret_cast<CodeGen *>(stage1); |
| 69 | 70 | |
| 70 | 71 | g->root_out_name = buf_create_from_mem(stage1->root_name_ptr, stage1->root_name_len); |
| 71 | g->zig_lib_dir = buf_create_from_mem(stage1->zig_lib_dir_ptr, stage1->zig_lib_dir_len); | |
| 72 | g->zig_std_dir = buf_create_from_mem(stage1->zig_std_dir_ptr, stage1->zig_std_dir_len); | |
| 73 | 72 | g->output_dir = buf_create_from_mem(stage1->output_dir_ptr, stage1->output_dir_len); |
| 74 | 73 | if (stage1->builtin_zig_path_len != 0) { |
| 75 | 74 | g->builtin_zig_path = buf_create_from_mem(stage1->builtin_zig_path_ptr, stage1->builtin_zig_path_len); |
| ... | ... | @@ -119,6 +118,8 @@ void zig_stage1_build_object(struct ZigStage1 *stage1) { |
| 119 | 118 | } |
| 120 | 119 | } |
| 121 | 120 | |
| 121 | g->main_progress_node = stage1->main_progress_node; | |
| 122 | ||
| 122 | 123 | add_package(g, stage1->root_pkg, g->main_pkg); |
| 123 | 124 | |
| 124 | 125 | codegen_build_object(g); |
src/stage1.h+6-19| ... | ... | @@ -100,22 +100,14 @@ enum Os { |
| 100 | 100 | // ABI warning |
| 101 | 101 | struct ZigTarget { |
| 102 | 102 | enum ZigLLVM_ArchType arch; |
| 103 | enum ZigLLVM_VendorType vendor; | |
| 104 | ||
| 103 | enum Os os; | |
| 105 | 104 | enum ZigLLVM_EnvironmentType abi; |
| 106 | Os os; | |
| 107 | 105 | |
| 108 | 106 | bool is_native_os; |
| 109 | 107 | bool is_native_cpu; |
| 110 | 108 | |
| 111 | 109 | const char *llvm_cpu_name; |
| 112 | 110 | const char *llvm_cpu_features; |
| 113 | const char *cpu_builtin_str; | |
| 114 | const char *os_builtin_str; | |
| 115 | const char *dynamic_linker; | |
| 116 | ||
| 117 | const char **llvm_cpu_features_asm_ptr; | |
| 118 | size_t llvm_cpu_features_asm_len; | |
| 119 | 111 | }; |
| 120 | 112 | |
| 121 | 113 | // ABI warning |
| ... | ... | @@ -161,18 +153,13 @@ struct ZigStage1 { |
| 161 | 153 | const char *test_name_prefix_ptr; |
| 162 | 154 | size_t test_name_prefix_len; |
| 163 | 155 | |
| 164 | const char *zig_lib_dir_ptr; | |
| 165 | size_t zig_lib_dir_len; | |
| 166 | ||
| 167 | const char *zig_std_dir_ptr; | |
| 168 | size_t zig_std_dir_len; | |
| 169 | ||
| 170 | 156 | void *userdata; |
| 171 | 157 | struct ZigStage1Pkg *root_pkg; |
| 158 | struct Stage2ProgressNode *main_progress_node; | |
| 172 | 159 | |
| 173 | CodeModel code_model; | |
| 174 | TargetSubsystem subsystem; | |
| 175 | ErrColor err_color; | |
| 160 | enum CodeModel code_model; | |
| 161 | enum TargetSubsystem subsystem; | |
| 162 | enum ErrColor err_color; | |
| 176 | 163 | |
| 177 | 164 | bool pic; |
| 178 | 165 | bool link_libc; |
| ... | ... | @@ -206,7 +193,7 @@ ZIG_EXTERN_C struct ZigStage1 *zig_stage1_create(enum BuildMode optimize_mode, |
| 206 | 193 | const char *main_pkg_path_ptr, size_t main_pkg_path_len, |
| 207 | 194 | const char *root_src_path_ptr, size_t root_src_path_len, |
| 208 | 195 | const char *zig_lib_dir_ptr, size_t zig_lib_dir_len, |
| 209 | const ZigTarget *target, bool is_test_build, Stage2ProgressNode *progress_node); | |
| 196 | const struct ZigTarget *target, bool is_test_build); | |
| 210 | 197 | |
| 211 | 198 | ZIG_EXTERN_C void zig_stage1_build_object(struct ZigStage1 *); |
| 212 | 199 |
src/stage2.cpp deleted-241| ... | ... | @@ -1,241 +0,0 @@ |
| 1 | // This file is a shim for zig1. The real implementations of these are in | |
| 2 | // src-self-hosted/stage1.zig | |
| 3 | ||
| 4 | #include "stage2.h" | |
| 5 | #include "util.hpp" | |
| 6 | #include "zig_llvm.h" | |
| 7 | #include "target.hpp" | |
| 8 | #include "buffer.hpp" | |
| 9 | #include "os.hpp" | |
| 10 | #include <stdio.h> | |
| 11 | #include <stdlib.h> | |
| 12 | #include <string.h> | |
| 13 | ||
| 14 | void stage2_panic(const char *ptr, size_t len) { | |
| 15 | fwrite(ptr, 1, len, stderr); | |
| 16 | fprintf(stderr, "\n"); | |
| 17 | fflush(stderr); | |
| 18 | abort(); | |
| 19 | } | |
| 20 | ||
| 21 | struct Stage2Progress { | |
| 22 | int trash; | |
| 23 | }; | |
| 24 | ||
| 25 | struct Stage2ProgressNode { | |
| 26 | int trash; | |
| 27 | }; | |
| 28 | ||
| 29 | Stage2Progress *stage2_progress_create(void) { | |
| 30 | return nullptr; | |
| 31 | } | |
| 32 | ||
| 33 | void stage2_progress_destroy(Stage2Progress *progress) {} | |
| 34 | ||
| 35 | Stage2ProgressNode *stage2_progress_start_root(Stage2Progress *progress, | |
| 36 | const char *name_ptr, size_t name_len, size_t estimated_total_items) | |
| 37 | { | |
| 38 | return nullptr; | |
| 39 | } | |
| 40 | Stage2ProgressNode *stage2_progress_start(Stage2ProgressNode *node, | |
| 41 | const char *name_ptr, size_t name_len, size_t estimated_total_items) | |
| 42 | { | |
| 43 | return nullptr; | |
| 44 | } | |
| 45 | void stage2_progress_end(Stage2ProgressNode *node) {} | |
| 46 | void stage2_progress_complete_one(Stage2ProgressNode *node) {} | |
| 47 | void stage2_progress_disable_tty(Stage2Progress *progress) {} | |
| 48 | void stage2_progress_update_node(Stage2ProgressNode *node, size_t completed_count, size_t estimated_total_items){} | |
| 49 | ||
| 50 | static Os get_zig_os_type(ZigLLVM_OSType os_type) { | |
| 51 | switch (os_type) { | |
| 52 | case ZigLLVM_UnknownOS: | |
| 53 | return OsFreestanding; | |
| 54 | case ZigLLVM_Ananas: | |
| 55 | return OsAnanas; | |
| 56 | case ZigLLVM_CloudABI: | |
| 57 | return OsCloudABI; | |
| 58 | case ZigLLVM_DragonFly: | |
| 59 | return OsDragonFly; | |
| 60 | case ZigLLVM_FreeBSD: | |
| 61 | return OsFreeBSD; | |
| 62 | case ZigLLVM_Fuchsia: | |
| 63 | return OsFuchsia; | |
| 64 | case ZigLLVM_IOS: | |
| 65 | return OsIOS; | |
| 66 | case ZigLLVM_KFreeBSD: | |
| 67 | return OsKFreeBSD; | |
| 68 | case ZigLLVM_Linux: | |
| 69 | return OsLinux; | |
| 70 | case ZigLLVM_Lv2: | |
| 71 | return OsLv2; | |
| 72 | case ZigLLVM_Darwin: | |
| 73 | case ZigLLVM_MacOSX: | |
| 74 | return OsMacOSX; | |
| 75 | case ZigLLVM_NetBSD: | |
| 76 | return OsNetBSD; | |
| 77 | case ZigLLVM_OpenBSD: | |
| 78 | return OsOpenBSD; | |
| 79 | case ZigLLVM_Solaris: | |
| 80 | return OsSolaris; | |
| 81 | case ZigLLVM_Win32: | |
| 82 | return OsWindows; | |
| 83 | case ZigLLVM_Haiku: | |
| 84 | return OsHaiku; | |
| 85 | case ZigLLVM_Minix: | |
| 86 | return OsMinix; | |
| 87 | case ZigLLVM_RTEMS: | |
| 88 | return OsRTEMS; | |
| 89 | case ZigLLVM_NaCl: | |
| 90 | return OsNaCl; | |
| 91 | case ZigLLVM_CNK: | |
| 92 | return OsCNK; | |
| 93 | case ZigLLVM_AIX: | |
| 94 | return OsAIX; | |
| 95 | case ZigLLVM_CUDA: | |
| 96 | return OsCUDA; | |
| 97 | case ZigLLVM_NVCL: | |
| 98 | return OsNVCL; | |
| 99 | case ZigLLVM_AMDHSA: | |
| 100 | return OsAMDHSA; | |
| 101 | case ZigLLVM_PS4: | |
| 102 | return OsPS4; | |
| 103 | case ZigLLVM_ELFIAMCU: | |
| 104 | return OsELFIAMCU; | |
| 105 | case ZigLLVM_TvOS: | |
| 106 | return OsTvOS; | |
| 107 | case ZigLLVM_WatchOS: | |
| 108 | return OsWatchOS; | |
| 109 | case ZigLLVM_Mesa3D: | |
| 110 | return OsMesa3D; | |
| 111 | case ZigLLVM_Contiki: | |
| 112 | return OsContiki; | |
| 113 | case ZigLLVM_AMDPAL: | |
| 114 | return OsAMDPAL; | |
| 115 | case ZigLLVM_HermitCore: | |
| 116 | return OsHermitCore; | |
| 117 | case ZigLLVM_Hurd: | |
| 118 | return OsHurd; | |
| 119 | case ZigLLVM_WASI: | |
| 120 | return OsWASI; | |
| 121 | case ZigLLVM_Emscripten: | |
| 122 | return OsEmscripten; | |
| 123 | } | |
| 124 | zig_unreachable(); | |
| 125 | } | |
| 126 | ||
| 127 | static void get_native_target(ZigTarget *target) { | |
| 128 | // first zero initialize | |
| 129 | *target = {}; | |
| 130 | ||
| 131 | ZigLLVM_OSType os_type; | |
| 132 | ZigLLVM_ObjectFormatType oformat; // ignored; based on arch/os | |
| 133 | ZigLLVMGetNativeTarget( | |
| 134 | &target->arch, | |
| 135 | &target->vendor, | |
| 136 | &os_type, | |
| 137 | &target->abi, | |
| 138 | &oformat); | |
| 139 | target->os = get_zig_os_type(os_type); | |
| 140 | target->is_native_os = true; | |
| 141 | target->is_native_cpu = true; | |
| 142 | if (target->abi == ZigLLVM_UnknownEnvironment) { | |
| 143 | target->abi = target_default_abi(target->arch, target->os); | |
| 144 | } | |
| 145 | } | |
| 146 | ||
| 147 | Error stage2_target_parse(struct ZigTarget *target, const char *zig_triple, const char *mcpu, | |
| 148 | const char *dynamic_linker) | |
| 149 | { | |
| 150 | Error err; | |
| 151 | ||
| 152 | if (zig_triple != nullptr && strcmp(zig_triple, "native") == 0) { | |
| 153 | zig_triple = nullptr; | |
| 154 | } | |
| 155 | ||
| 156 | if (zig_triple == nullptr) { | |
| 157 | get_native_target(target); | |
| 158 | ||
| 159 | if (mcpu == nullptr) { | |
| 160 | target->llvm_cpu_name = ZigLLVMGetHostCPUName(); | |
| 161 | target->llvm_cpu_features = ZigLLVMGetNativeFeatures(); | |
| 162 | } else if (strcmp(mcpu, "baseline") == 0) { | |
| 163 | target->is_native_os = false; | |
| 164 | target->is_native_cpu = false; | |
| 165 | target->llvm_cpu_name = ""; | |
| 166 | target->llvm_cpu_features = ""; | |
| 167 | } else { | |
| 168 | const char *msg = "stage0 can't handle CPU/features in the target"; | |
| 169 | stage2_panic(msg, strlen(msg)); | |
| 170 | } | |
| 171 | } else { | |
| 172 | // first initialize all to zero | |
| 173 | *target = {}; | |
| 174 | ||
| 175 | SplitIterator it = memSplit(str(zig_triple), str("-")); | |
| 176 | ||
| 177 | Optional<Slice<uint8_t>> opt_archsub = SplitIterator_next(&it); | |
| 178 | Optional<Slice<uint8_t>> opt_os = SplitIterator_next(&it); | |
| 179 | Optional<Slice<uint8_t>> opt_abi = SplitIterator_next(&it); | |
| 180 | ||
| 181 | if (!opt_archsub.is_some) | |
| 182 | return ErrorMissingArchitecture; | |
| 183 | ||
| 184 | if ((err = target_parse_arch(&target->arch, (char*)opt_archsub.value.ptr, opt_archsub.value.len))) { | |
| 185 | return err; | |
| 186 | } | |
| 187 | ||
| 188 | if (!opt_os.is_some) | |
| 189 | return ErrorMissingOperatingSystem; | |
| 190 | ||
| 191 | if ((err = target_parse_os(&target->os, (char*)opt_os.value.ptr, opt_os.value.len))) { | |
| 192 | return err; | |
| 193 | } | |
| 194 | ||
| 195 | if (opt_abi.is_some) { | |
| 196 | if ((err = target_parse_abi(&target->abi, (char*)opt_abi.value.ptr, opt_abi.value.len))) { | |
| 197 | return err; | |
| 198 | } | |
| 199 | } else { | |
| 200 | target->abi = target_default_abi(target->arch, target->os); | |
| 201 | } | |
| 202 | ||
| 203 | if (mcpu != nullptr && strcmp(mcpu, "baseline") != 0) { | |
| 204 | const char *msg = "stage0 can't handle CPU/features in the target"; | |
| 205 | stage2_panic(msg, strlen(msg)); | |
| 206 | } | |
| 207 | } | |
| 208 | ||
| 209 | if (dynamic_linker != nullptr) { | |
| 210 | target->dynamic_linker = dynamic_linker; | |
| 211 | } | |
| 212 | ||
| 213 | return ErrorNone; | |
| 214 | } | |
| 215 | ||
| 216 | const char *stage2_fetch_file(struct ZigStage1 *stage1, const char *path_ptr, size_t path_len, | |
| 217 | size_t *result_len) | |
| 218 | { | |
| 219 | Error err; | |
| 220 | Buf contents_buf = BUF_INIT; | |
| 221 | Buf path_buf = BUF_INIT; | |
| 222 | ||
| 223 | buf_init_from_mem(&path_buf, path_ptr, path_len); | |
| 224 | if ((err = os_fetch_file_path(&path_buf, &contents_buf))) { | |
| 225 | return nullptr; | |
| 226 | } | |
| 227 | *result_len = buf_len(&contents_buf); | |
| 228 | return buf_ptr(&contents_buf); | |
| 229 | } | |
| 230 | ||
| 231 | const char *stage2_cimport(struct ZigStage1 *stage1) { | |
| 232 | const char *msg = "stage0 called stage2_cimport"; | |
| 233 | stage2_panic(msg, strlen(msg)); | |
| 234 | } | |
| 235 | ||
| 236 | const char *stage2_add_link_lib(struct ZigStage1 *stage1, | |
| 237 | const char *lib_name_ptr, size_t lib_name_len, | |
| 238 | const char *symbol_name_ptr, size_t symbol_name_len) | |
| 239 | { | |
| 240 | return nullptr; | |
| 241 | } |
src/stage2.h+8-8| ... | ... | @@ -130,23 +130,23 @@ struct Stage2ErrorMsg { |
| 130 | 130 | ZIG_EXTERN_C ZIG_ATTRIBUTE_NORETURN void stage2_panic(const char *ptr, size_t len); |
| 131 | 131 | |
| 132 | 132 | // ABI warning |
| 133 | ZIG_EXTERN_C Stage2Progress *stage2_progress_create(void); | |
| 133 | ZIG_EXTERN_C struct Stage2Progress *stage2_progress_create(void); | |
| 134 | 134 | // ABI warning |
| 135 | ZIG_EXTERN_C void stage2_progress_disable_tty(Stage2Progress *progress); | |
| 135 | ZIG_EXTERN_C void stage2_progress_disable_tty(struct Stage2Progress *progress); | |
| 136 | 136 | // ABI warning |
| 137 | ZIG_EXTERN_C void stage2_progress_destroy(Stage2Progress *progress); | |
| 137 | ZIG_EXTERN_C void stage2_progress_destroy(struct Stage2Progress *progress); | |
| 138 | 138 | // ABI warning |
| 139 | ZIG_EXTERN_C Stage2ProgressNode *stage2_progress_start_root(Stage2Progress *progress, | |
| 139 | ZIG_EXTERN_C struct Stage2ProgressNode *stage2_progress_start_root(struct Stage2Progress *progress, | |
| 140 | 140 | const char *name_ptr, size_t name_len, size_t estimated_total_items); |
| 141 | 141 | // ABI warning |
| 142 | ZIG_EXTERN_C Stage2ProgressNode *stage2_progress_start(Stage2ProgressNode *node, | |
| 142 | ZIG_EXTERN_C struct Stage2ProgressNode *stage2_progress_start(struct Stage2ProgressNode *node, | |
| 143 | 143 | const char *name_ptr, size_t name_len, size_t estimated_total_items); |
| 144 | 144 | // ABI warning |
| 145 | ZIG_EXTERN_C void stage2_progress_end(Stage2ProgressNode *node); | |
| 145 | ZIG_EXTERN_C void stage2_progress_end(struct Stage2ProgressNode *node); | |
| 146 | 146 | // ABI warning |
| 147 | ZIG_EXTERN_C void stage2_progress_complete_one(Stage2ProgressNode *node); | |
| 147 | ZIG_EXTERN_C void stage2_progress_complete_one(struct Stage2ProgressNode *node); | |
| 148 | 148 | // ABI warning |
| 149 | ZIG_EXTERN_C void stage2_progress_update_node(Stage2ProgressNode *node, | |
| 149 | ZIG_EXTERN_C void stage2_progress_update_node(struct Stage2ProgressNode *node, | |
| 150 | 150 | size_t completed_count, size_t estimated_total_items); |
| 151 | 151 | |
| 152 | 152 | // ABI warning |
src/target.cpp+1-6| ... | ... | @@ -380,10 +380,6 @@ Error target_parse_abi(ZigLLVM_EnvironmentType *out_abi, const char *abi_ptr, si |
| 380 | 380 | return ErrorUnknownABI; |
| 381 | 381 | } |
| 382 | 382 | |
| 383 | Error target_parse_triple(ZigTarget *target, const char *triple, const char *mcpu, const char *dynamic_linker) { | |
| 384 | return stage2_target_parse(target, triple, mcpu, dynamic_linker); | |
| 385 | } | |
| 386 | ||
| 387 | 383 | const char *target_arch_name(ZigLLVM_ArchType arch) { |
| 388 | 384 | return ZigLLVMGetArchTypeName(arch); |
| 389 | 385 | } |
| ... | ... | @@ -408,7 +404,7 @@ void target_triple_llvm(Buf *triple, const ZigTarget *target) { |
| 408 | 404 | buf_resize(triple, 0); |
| 409 | 405 | buf_appendf(triple, "%s-%s-%s-%s", |
| 410 | 406 | ZigLLVMGetArchTypeName(target->arch), |
| 411 | ZigLLVMGetVendorTypeName(target->vendor), | |
| 407 | ZigLLVMGetVendorTypeName(ZigLLVM_UnknownVendor), | |
| 412 | 408 | ZigLLVMGetOSTypeName(get_llvm_os_type(target->os)), |
| 413 | 409 | ZigLLVMGetEnvironmentTypeName(target->abi)); |
| 414 | 410 | } |
| ... | ... | @@ -1149,7 +1145,6 @@ void target_libc_enum(size_t index, ZigTarget *out_target) { |
| 1149 | 1145 | out_target->arch = libcs_available[index].arch; |
| 1150 | 1146 | out_target->os = libcs_available[index].os; |
| 1151 | 1147 | out_target->abi = libcs_available[index].abi; |
| 1152 | out_target->vendor = ZigLLVM_UnknownVendor; | |
| 1153 | 1148 | out_target->is_native_os = false; |
| 1154 | 1149 | out_target->is_native_cpu = false; |
| 1155 | 1150 | } |
src/target.hpp-1| ... | ... | @@ -25,7 +25,6 @@ enum CIntType { |
| 25 | 25 | CIntTypeCount, |
| 26 | 26 | }; |
| 27 | 27 | |
| 28 | Error target_parse_triple(ZigTarget *target, const char *triple, const char *mcpu, const char *dynamic_linker); | |
| 29 | 28 | Error target_parse_arch(ZigLLVM_ArchType *arch, const char *arch_ptr, size_t arch_len); |
| 30 | 29 | Error target_parse_os(Os *os, const char *os_ptr, size_t os_len); |
| 31 | 30 | Error target_parse_abi(ZigLLVM_EnvironmentType *abi, const char *abi_ptr, size_t abi_len); |
src/zig0.cpp+239-12| ... | ... | @@ -14,6 +14,9 @@ |
| 14 | 14 | #include "stage2.h" |
| 15 | 15 | #include "target.hpp" |
| 16 | 16 | #include "error.hpp" |
| 17 | #include "util.hpp" | |
| 18 | #include "buffer.hpp" | |
| 19 | #include "os.hpp" | |
| 17 | 20 | |
| 18 | 21 | #include <stdio.h> |
| 19 | 22 | #include <string.h> |
| ... | ... | @@ -33,7 +36,6 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) { |
| 33 | 36 | " --output-dir [dir] override output directory (defaults to cwd)\n" |
| 34 | 37 | " --pkg-begin [name] [path] make pkg available to import and push current pkg\n" |
| 35 | 38 | " --pkg-end pop current pkg\n" |
| 36 | " --main-pkg-path set the directory of the root package\n" | |
| 37 | 39 | " --release-fast build with optimizations on and safety off\n" |
| 38 | 40 | " --release-safe build with optimizations on and safety on\n" |
| 39 | 41 | " --release-small build with size optimizations on and safety off\n" |
| ... | ... | @@ -53,6 +55,170 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) { |
| 53 | 55 | return return_code; |
| 54 | 56 | } |
| 55 | 57 | |
| 58 | static Os get_zig_os_type(ZigLLVM_OSType os_type) { | |
| 59 | switch (os_type) { | |
| 60 | case ZigLLVM_UnknownOS: | |
| 61 | return OsFreestanding; | |
| 62 | case ZigLLVM_Ananas: | |
| 63 | return OsAnanas; | |
| 64 | case ZigLLVM_CloudABI: | |
| 65 | return OsCloudABI; | |
| 66 | case ZigLLVM_DragonFly: | |
| 67 | return OsDragonFly; | |
| 68 | case ZigLLVM_FreeBSD: | |
| 69 | return OsFreeBSD; | |
| 70 | case ZigLLVM_Fuchsia: | |
| 71 | return OsFuchsia; | |
| 72 | case ZigLLVM_IOS: | |
| 73 | return OsIOS; | |
| 74 | case ZigLLVM_KFreeBSD: | |
| 75 | return OsKFreeBSD; | |
| 76 | case ZigLLVM_Linux: | |
| 77 | return OsLinux; | |
| 78 | case ZigLLVM_Lv2: | |
| 79 | return OsLv2; | |
| 80 | case ZigLLVM_Darwin: | |
| 81 | case ZigLLVM_MacOSX: | |
| 82 | return OsMacOSX; | |
| 83 | case ZigLLVM_NetBSD: | |
| 84 | return OsNetBSD; | |
| 85 | case ZigLLVM_OpenBSD: | |
| 86 | return OsOpenBSD; | |
| 87 | case ZigLLVM_Solaris: | |
| 88 | return OsSolaris; | |
| 89 | case ZigLLVM_Win32: | |
| 90 | return OsWindows; | |
| 91 | case ZigLLVM_Haiku: | |
| 92 | return OsHaiku; | |
| 93 | case ZigLLVM_Minix: | |
| 94 | return OsMinix; | |
| 95 | case ZigLLVM_RTEMS: | |
| 96 | return OsRTEMS; | |
| 97 | case ZigLLVM_NaCl: | |
| 98 | return OsNaCl; | |
| 99 | case ZigLLVM_CNK: | |
| 100 | return OsCNK; | |
| 101 | case ZigLLVM_AIX: | |
| 102 | return OsAIX; | |
| 103 | case ZigLLVM_CUDA: | |
| 104 | return OsCUDA; | |
| 105 | case ZigLLVM_NVCL: | |
| 106 | return OsNVCL; | |
| 107 | case ZigLLVM_AMDHSA: | |
| 108 | return OsAMDHSA; | |
| 109 | case ZigLLVM_PS4: | |
| 110 | return OsPS4; | |
| 111 | case ZigLLVM_ELFIAMCU: | |
| 112 | return OsELFIAMCU; | |
| 113 | case ZigLLVM_TvOS: | |
| 114 | return OsTvOS; | |
| 115 | case ZigLLVM_WatchOS: | |
| 116 | return OsWatchOS; | |
| 117 | case ZigLLVM_Mesa3D: | |
| 118 | return OsMesa3D; | |
| 119 | case ZigLLVM_Contiki: | |
| 120 | return OsContiki; | |
| 121 | case ZigLLVM_AMDPAL: | |
| 122 | return OsAMDPAL; | |
| 123 | case ZigLLVM_HermitCore: | |
| 124 | return OsHermitCore; | |
| 125 | case ZigLLVM_Hurd: | |
| 126 | return OsHurd; | |
| 127 | case ZigLLVM_WASI: | |
| 128 | return OsWASI; | |
| 129 | case ZigLLVM_Emscripten: | |
| 130 | return OsEmscripten; | |
| 131 | } | |
| 132 | zig_unreachable(); | |
| 133 | } | |
| 134 | ||
| 135 | static void get_native_target(ZigTarget *target) { | |
| 136 | // first zero initialize | |
| 137 | *target = {}; | |
| 138 | ||
| 139 | ZigLLVM_OSType os_type; | |
| 140 | ZigLLVM_ObjectFormatType oformat; // ignored; based on arch/os | |
| 141 | ZigLLVM_VendorType trash; | |
| 142 | ZigLLVMGetNativeTarget( | |
| 143 | &target->arch, | |
| 144 | &trash, | |
| 145 | &os_type, | |
| 146 | &target->abi, | |
| 147 | &oformat); | |
| 148 | target->os = get_zig_os_type(os_type); | |
| 149 | target->is_native_os = true; | |
| 150 | target->is_native_cpu = true; | |
| 151 | if (target->abi == ZigLLVM_UnknownEnvironment) { | |
| 152 | target->abi = target_default_abi(target->arch, target->os); | |
| 153 | } | |
| 154 | } | |
| 155 | ||
| 156 | static Error target_parse_triple(struct ZigTarget *target, const char *zig_triple, const char *mcpu, | |
| 157 | const char *dynamic_linker) | |
| 158 | { | |
| 159 | Error err; | |
| 160 | ||
| 161 | if (zig_triple != nullptr && strcmp(zig_triple, "native") == 0) { | |
| 162 | zig_triple = nullptr; | |
| 163 | } | |
| 164 | ||
| 165 | if (zig_triple == nullptr) { | |
| 166 | get_native_target(target); | |
| 167 | ||
| 168 | if (mcpu == nullptr) { | |
| 169 | target->llvm_cpu_name = ZigLLVMGetHostCPUName(); | |
| 170 | target->llvm_cpu_features = ZigLLVMGetNativeFeatures(); | |
| 171 | } else if (strcmp(mcpu, "baseline") == 0) { | |
| 172 | target->is_native_os = false; | |
| 173 | target->is_native_cpu = false; | |
| 174 | target->llvm_cpu_name = ""; | |
| 175 | target->llvm_cpu_features = ""; | |
| 176 | } else { | |
| 177 | const char *msg = "stage0 can't handle CPU/features in the target"; | |
| 178 | stage2_panic(msg, strlen(msg)); | |
| 179 | } | |
| 180 | } else { | |
| 181 | // first initialize all to zero | |
| 182 | *target = {}; | |
| 183 | ||
| 184 | SplitIterator it = memSplit(str(zig_triple), str("-")); | |
| 185 | ||
| 186 | Optional<Slice<uint8_t>> opt_archsub = SplitIterator_next(&it); | |
| 187 | Optional<Slice<uint8_t>> opt_os = SplitIterator_next(&it); | |
| 188 | Optional<Slice<uint8_t>> opt_abi = SplitIterator_next(&it); | |
| 189 | ||
| 190 | if (!opt_archsub.is_some) | |
| 191 | return ErrorMissingArchitecture; | |
| 192 | ||
| 193 | if ((err = target_parse_arch(&target->arch, (char*)opt_archsub.value.ptr, opt_archsub.value.len))) { | |
| 194 | return err; | |
| 195 | } | |
| 196 | ||
| 197 | if (!opt_os.is_some) | |
| 198 | return ErrorMissingOperatingSystem; | |
| 199 | ||
| 200 | if ((err = target_parse_os(&target->os, (char*)opt_os.value.ptr, opt_os.value.len))) { | |
| 201 | return err; | |
| 202 | } | |
| 203 | ||
| 204 | if (opt_abi.is_some) { | |
| 205 | if ((err = target_parse_abi(&target->abi, (char*)opt_abi.value.ptr, opt_abi.value.len))) { | |
| 206 | return err; | |
| 207 | } | |
| 208 | } else { | |
| 209 | target->abi = target_default_abi(target->arch, target->os); | |
| 210 | } | |
| 211 | ||
| 212 | if (mcpu != nullptr && strcmp(mcpu, "baseline") != 0) { | |
| 213 | const char *msg = "stage0 can't handle CPU/features in the target"; | |
| 214 | stage2_panic(msg, strlen(msg)); | |
| 215 | } | |
| 216 | } | |
| 217 | ||
| 218 | return ErrorNone; | |
| 219 | } | |
| 220 | ||
| 221 | ||
| 56 | 222 | static bool str_starts_with(const char *s1, const char *s2) { |
| 57 | 223 | size_t s2_len = strlen(s2); |
| 58 | 224 | if (strlen(s1) < s2_len) { |
| ... | ... | @@ -90,10 +256,9 @@ int main(int argc, char **argv) { |
| 90 | 256 | bool link_libcpp = false; |
| 91 | 257 | const char *target_string = nullptr; |
| 92 | 258 | ZigStage1Pkg *cur_pkg = heap::c_allocator.create<ZigStage1Pkg>(); |
| 93 | BuildMode build_mode = BuildModeDebug; | |
| 259 | BuildMode optimize_mode = BuildModeDebug; | |
| 94 | 260 | TargetSubsystem subsystem = TargetSubsystemAuto; |
| 95 | 261 | const char *override_lib_dir = nullptr; |
| 96 | const char *main_pkg_path = nullptr; | |
| 97 | 262 | const char *mcpu = nullptr; |
| 98 | 263 | |
| 99 | 264 | for (int i = 1; i < argc; i += 1) { |
| ... | ... | @@ -103,11 +268,11 @@ int main(int argc, char **argv) { |
| 103 | 268 | if (strcmp(arg, "--") == 0) { |
| 104 | 269 | fprintf(stderr, "Unexpected end-of-parameter mark: %s\n", arg); |
| 105 | 270 | } else if (strcmp(arg, "--release-fast") == 0) { |
| 106 | build_mode = BuildModeFastRelease; | |
| 271 | optimize_mode = BuildModeFastRelease; | |
| 107 | 272 | } else if (strcmp(arg, "--release-safe") == 0) { |
| 108 | build_mode = BuildModeSafeRelease; | |
| 273 | optimize_mode = BuildModeSafeRelease; | |
| 109 | 274 | } else if (strcmp(arg, "--release-small") == 0) { |
| 110 | build_mode = BuildModeSmallRelease; | |
| 275 | optimize_mode = BuildModeSmallRelease; | |
| 111 | 276 | } else if (strcmp(arg, "--help") == 0) { |
| 112 | 277 | return print_full_usage(arg0, stdout, EXIT_SUCCESS); |
| 113 | 278 | } else if (strcmp(arg, "--strip") == 0) { |
| ... | ... | @@ -183,8 +348,6 @@ int main(int argc, char **argv) { |
| 183 | 348 | dynamic_linker = argv[i]; |
| 184 | 349 | } else if (strcmp(arg, "--override-lib-dir") == 0) { |
| 185 | 350 | override_lib_dir = argv[i]; |
| 186 | } else if (strcmp(arg, "--main-pkg-path") == 0) { | |
| 187 | main_pkg_path = argv[i]; | |
| 188 | 351 | } else if (strcmp(arg, "--library") == 0 || strcmp(arg, "-l") == 0) { |
| 189 | 352 | if (strcmp(argv[i], "c") == 0) { |
| 190 | 353 | link_libc = true; |
| ... | ... | @@ -264,12 +427,13 @@ int main(int argc, char **argv) { |
| 264 | 427 | return print_error_usage(arg0); |
| 265 | 428 | } |
| 266 | 429 | |
| 267 | ZigStage1 *stage1 = zig_stage1_create(build_mode, | |
| 268 | main_pkg_path, (main_pkg_path == nullptr) ? 0 : strlen(main_pkg_path), | |
| 430 | ZigStage1 *stage1 = zig_stage1_create(optimize_mode, | |
| 431 | nullptr, 0, | |
| 269 | 432 | in_file, strlen(in_file), |
| 270 | override_lib_dir, strlen(override_lib_dir), &target, false, | |
| 271 | root_progress_node); | |
| 433 | override_lib_dir, strlen(override_lib_dir), | |
| 434 | &target, false); | |
| 272 | 435 | |
| 436 | stage1->main_progress_node = root_progress_node; | |
| 273 | 437 | stage1->root_name_ptr = out_name; |
| 274 | 438 | stage1->root_name_len = strlen(out_name); |
| 275 | 439 | stage1->strip = strip; |
| ... | ... | @@ -295,3 +459,66 @@ int main(int argc, char **argv) { |
| 295 | 459 | |
| 296 | 460 | return main_exit(root_progress_node, EXIT_SUCCESS); |
| 297 | 461 | } |
| 462 | ||
| 463 | void stage2_panic(const char *ptr, size_t len) { | |
| 464 | fwrite(ptr, 1, len, stderr); | |
| 465 | fprintf(stderr, "\n"); | |
| 466 | fflush(stderr); | |
| 467 | abort(); | |
| 468 | } | |
| 469 | ||
| 470 | struct Stage2Progress { | |
| 471 | int trash; | |
| 472 | }; | |
| 473 | ||
| 474 | struct Stage2ProgressNode { | |
| 475 | int trash; | |
| 476 | }; | |
| 477 | ||
| 478 | Stage2Progress *stage2_progress_create(void) { | |
| 479 | return nullptr; | |
| 480 | } | |
| 481 | ||
| 482 | void stage2_progress_destroy(Stage2Progress *progress) {} | |
| 483 | ||
| 484 | Stage2ProgressNode *stage2_progress_start_root(Stage2Progress *progress, | |
| 485 | const char *name_ptr, size_t name_len, size_t estimated_total_items) | |
| 486 | { | |
| 487 | return nullptr; | |
| 488 | } | |
| 489 | Stage2ProgressNode *stage2_progress_start(Stage2ProgressNode *node, | |
| 490 | const char *name_ptr, size_t name_len, size_t estimated_total_items) | |
| 491 | { | |
| 492 | return nullptr; | |
| 493 | } | |
| 494 | void stage2_progress_end(Stage2ProgressNode *node) {} | |
| 495 | void stage2_progress_complete_one(Stage2ProgressNode *node) {} | |
| 496 | void stage2_progress_disable_tty(Stage2Progress *progress) {} | |
| 497 | void stage2_progress_update_node(Stage2ProgressNode *node, size_t completed_count, size_t estimated_total_items){} | |
| 498 | ||
| 499 | const char *stage2_fetch_file(struct ZigStage1 *stage1, const char *path_ptr, size_t path_len, | |
| 500 | size_t *result_len) | |
| 501 | { | |
| 502 | Error err; | |
| 503 | Buf contents_buf = BUF_INIT; | |
| 504 | Buf path_buf = BUF_INIT; | |
| 505 | ||
| 506 | buf_init_from_mem(&path_buf, path_ptr, path_len); | |
| 507 | if ((err = os_fetch_file_path(&path_buf, &contents_buf))) { | |
| 508 | return nullptr; | |
| 509 | } | |
| 510 | *result_len = buf_len(&contents_buf); | |
| 511 | return buf_ptr(&contents_buf); | |
| 512 | } | |
| 513 | ||
| 514 | const char *stage2_cimport(struct ZigStage1 *stage1) { | |
| 515 | const char *msg = "stage0 called stage2_cimport"; | |
| 516 | stage2_panic(msg, strlen(msg)); | |
| 517 | } | |
| 518 | ||
| 519 | const char *stage2_add_link_lib(struct ZigStage1 *stage1, | |
| 520 | const char *lib_name_ptr, size_t lib_name_len, | |
| 521 | const char *symbol_name_ptr, size_t symbol_name_len) | |
| 522 | { | |
| 523 | return nullptr; | |
| 524 | } |