authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-02-16 19:16:08-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-02-16 19:16:08-05:00
log20f3b0efff76cb3c611b72c1c1862490aef79b80
treea7480ae1b27776576f12392a798c18c2fb293be5
parentc25742010d69e0e56f1fda99f1b986be52165e3b

rename libuserland to libstage2


15 files changed, 1486 insertions(+), 1486 deletions(-)

CMakeLists.txt+17-17
......@@ -434,8 +434,8 @@ find_package(Threads)
434434# CMake doesn't let us create an empty executable, so we hang on to this one separately.
435435set(ZIG_MAIN_SRC "${CMAKE_SOURCE_DIR}/src/main.cpp")
436436
437# This is our shim which will be replaced by libuserland written in Zig.
438set(ZIG0_SHIM_SRC "${CMAKE_SOURCE_DIR}/src/userland.cpp")
437# This is our shim which will be replaced by libstage2 written in Zig.
438set(ZIG0_SHIM_SRC "${CMAKE_SOURCE_DIR}/src/stage2.cpp")
439439
440440if(ZIG_ENABLE_MEM_PROFILE)
441441 set(ZIG_SOURCES_MEM_PROFILE "${CMAKE_SOURCE_DIR}/src/mem_profile.cpp")
......@@ -599,38 +599,38 @@ set_target_properties(zig0 PROPERTIES
599599target_link_libraries(zig0 compiler)
600600
601601if(MSVC)
602 set(LIBUSERLAND "${CMAKE_BINARY_DIR}/userland.lib")
602 set(LIBSTAGE2 "${CMAKE_BINARY_DIR}/stage2.lib")
603603else()
604 set(LIBUSERLAND "${CMAKE_BINARY_DIR}/libuserland.a")
604 set(LIBSTAGE2 "${CMAKE_BINARY_DIR}/libstage2.a")
605605endif()
606606if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
607 set(LIBUSERLAND_RELEASE_ARG "")
607 set(LIBSTAGE2_RELEASE_ARG "")
608608else()
609 set(LIBUSERLAND_RELEASE_ARG --release-fast --strip)
609 set(LIBSTAGE2_RELEASE_ARG --release-fast --strip)
610610endif()
611611if(WIN32)
612 set(LIBUSERLAND_WINDOWS_ARGS "-lntdll")
612 set(LIBSTAGE2_WINDOWS_ARGS "-lntdll")
613613else()
614 set(LIBUSERLAND_WINDOWS_ARGS "")
614 set(LIBSTAGE2_WINDOWS_ARGS "")
615615endif()
616616
617set(BUILD_LIBUSERLAND_ARGS "build-lib"
617set(BUILD_LIBSTAGE2_ARGS "build-lib"
618618 --override-lib-dir "${CMAKE_SOURCE_DIR}/lib"
619619 --cache on
620620 --output-dir "${CMAKE_BINARY_DIR}"
621 ${LIBUSERLAND_RELEASE_ARG}
622 "src-self-hosted/stage1.zig"
621 ${LIBSTAGE2_RELEASE_ARG}
622 "src-self-hosted/stage2.zig"
623623 --disable-gen-h
624624 --bundle-compiler-rt
625625 -fPIC
626626 -lc
627 ${LIBUSERLAND_WINDOWS_ARGS}
627 ${LIBSTAGE2_WINDOWS_ARGS}
628628)
629629
630add_custom_target(zig_build_libuserland ALL
631 COMMAND zig0 ${BUILD_LIBUSERLAND_ARGS}
630add_custom_target(zig_build_libstage2 ALL
631 COMMAND zig0 ${BUILD_LIBSTAGE2_ARGS}
632632 DEPENDS zig0
633 BYPRODUCTS "${LIBUSERLAND}"
633 BYPRODUCTS "${LIBSTAGE2}"
634634 WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
635635)
636636add_executable(zig "${ZIG_MAIN_SRC}")
......@@ -639,13 +639,13 @@ set_target_properties(zig PROPERTIES
639639 COMPILE_FLAGS ${EXE_CFLAGS}
640640 LINK_FLAGS ${EXE_LDFLAGS}
641641)
642target_link_libraries(zig compiler "${LIBUSERLAND}")
642target_link_libraries(zig compiler "${LIBSTAGE2}")
643643if(MSVC)
644644 target_link_libraries(zig ntdll.lib)
645645elseif(MINGW)
646646 target_link_libraries(zig ntdll)
647647endif()
648add_dependencies(zig zig_build_libuserland)
648add_dependencies(zig zig_build_libstage2)
649649
650650install(TARGETS zig DESTINATION bin)
651651
cmake/install.cmake+2-2
......@@ -19,9 +19,9 @@ if(_result)
1919 message(":: ERROR: ${_result}")
2020 message(":: (execute_process)")
2121
22 string(REPLACE ";" " " s_INSTALL_LIBUSERLAND_ARGS "${ZIG_INSTALL_ARGS}")
22 string(REPLACE ";" " " s_INSTALL_LIBSTAGE2_ARGS "${ZIG_INSTALL_ARGS}")
2323 message("::")
24 message(":: argv: ${zig_EXE} ${s_INSTALL_LIBUSERLAND_ARGS}")
24 message(":: argv: ${zig_EXE} ${s_INSTALL_LIBSTAGE2_ARGS}")
2525
2626 set(_args ${zig_EXE} ${ZIG_INSTALL_ARGS})
2727 list(LENGTH _args _len)
src-self-hosted/stage1.zig deleted-1033
......@@ -1,1033 +0,0 @@
1// This is Zig code that is used by both stage1 and stage2.
2// The prototypes in src/userland.h must match these definitions.
3
4const std = @import("std");
5const io = std.io;
6const mem = std.mem;
7const fs = std.fs;
8const process = std.process;
9const Allocator = mem.Allocator;
10const ArrayList = std.ArrayList;
11const Buffer = std.Buffer;
12const Target = std.Target;
13const self_hosted_main = @import("main.zig");
14const errmsg = @import("errmsg.zig");
15const DepTokenizer = @import("dep_tokenizer.zig").Tokenizer;
16const assert = std.debug.assert;
17const LibCInstallation = @import("libc_installation.zig").LibCInstallation;
18
19var stderr_file: fs.File = undefined;
20var stderr: *io.OutStream(fs.File.WriteError) = undefined;
21var stdout: *io.OutStream(fs.File.WriteError) = undefined;
22
23comptime {
24 _ = @import("dep_tokenizer.zig");
25}
26
27// ABI warning
28export fn stage2_zen(ptr: *[*]const u8, len: *usize) void {
29 const info_zen = @import("main.zig").info_zen;
30 ptr.* = info_zen;
31 len.* = info_zen.len;
32}
33
34// ABI warning
35export fn stage2_panic(ptr: [*]const u8, len: usize) void {
36 @panic(ptr[0..len]);
37}
38
39// ABI warning
40const Error = extern enum {
41 None,
42 OutOfMemory,
43 InvalidFormat,
44 SemanticAnalyzeFail,
45 AccessDenied,
46 Interrupted,
47 SystemResources,
48 FileNotFound,
49 FileSystem,
50 FileTooBig,
51 DivByZero,
52 Overflow,
53 PathAlreadyExists,
54 Unexpected,
55 ExactDivRemainder,
56 NegativeDenominator,
57 ShiftedOutOneBits,
58 CCompileErrors,
59 EndOfFile,
60 IsDir,
61 NotDir,
62 UnsupportedOperatingSystem,
63 SharingViolation,
64 PipeBusy,
65 PrimitiveTypeNotFound,
66 CacheUnavailable,
67 PathTooLong,
68 CCompilerCannotFindFile,
69 NoCCompilerInstalled,
70 ReadingDepFile,
71 InvalidDepFile,
72 MissingArchitecture,
73 MissingOperatingSystem,
74 UnknownArchitecture,
75 UnknownOperatingSystem,
76 UnknownABI,
77 InvalidFilename,
78 DiskQuota,
79 DiskSpace,
80 UnexpectedWriteFailure,
81 UnexpectedSeekFailure,
82 UnexpectedFileTruncationFailure,
83 Unimplemented,
84 OperationAborted,
85 BrokenPipe,
86 NoSpaceLeft,
87 NotLazy,
88 IsAsync,
89 ImportOutsidePkgPath,
90 UnknownCpu,
91 UnknownSubArchitecture,
92 UnknownCpuFeature,
93 InvalidCpuFeatures,
94 InvalidLlvmCpuFeaturesFormat,
95 UnknownApplicationBinaryInterface,
96 ASTUnitFailure,
97 BadPathName,
98 SymLinkLoop,
99 ProcessFdQuotaExceeded,
100 SystemFdQuotaExceeded,
101 NoDevice,
102 DeviceBusy,
103 UnableToSpawnCCompiler,
104 CCompilerExitCode,
105 CCompilerCrashed,
106 CCompilerCannotFindHeaders,
107 LibCRuntimeNotFound,
108 LibCStdLibHeaderNotFound,
109 LibCKernel32LibNotFound,
110 UnsupportedArchitecture,
111};
112
113const FILE = std.c.FILE;
114const ast = std.zig.ast;
115const translate_c = @import("translate_c.zig");
116
117/// Args should have a null terminating last arg.
118export fn stage2_translate_c(
119 out_ast: **ast.Tree,
120 out_errors_ptr: *[*]translate_c.ClangErrMsg,
121 out_errors_len: *usize,
122 args_begin: [*]?[*]const u8,
123 args_end: [*]?[*]const u8,
124 resources_path: [*:0]const u8,
125) Error {
126 var errors = @as([*]translate_c.ClangErrMsg, undefined)[0..0];
127 out_ast.* = translate_c.translate(std.heap.c_allocator, args_begin, args_end, &errors, resources_path) catch |err| switch (err) {
128 error.SemanticAnalyzeFail => {
129 out_errors_ptr.* = errors.ptr;
130 out_errors_len.* = errors.len;
131 return .CCompileErrors;
132 },
133 error.ASTUnitFailure => return .ASTUnitFailure,
134 error.OutOfMemory => return .OutOfMemory,
135 };
136 return .None;
137}
138
139export fn stage2_free_clang_errors(errors_ptr: [*]translate_c.ClangErrMsg, errors_len: usize) void {
140 translate_c.freeErrors(errors_ptr[0..errors_len]);
141}
142
143export fn stage2_render_ast(tree: *ast.Tree, output_file: *FILE) Error {
144 const c_out_stream = &std.io.COutStream.init(output_file).stream;
145 _ = std.zig.render(std.heap.c_allocator, c_out_stream, tree) catch |e| switch (e) {
146 error.WouldBlock => unreachable, // stage1 opens stuff in exclusively blocking mode
147 error.SystemResources => return .SystemResources,
148 error.OperationAborted => return .OperationAborted,
149 error.BrokenPipe => return .BrokenPipe,
150 error.DiskQuota => return .DiskQuota,
151 error.FileTooBig => return .FileTooBig,
152 error.NoSpaceLeft => return .NoSpaceLeft,
153 error.AccessDenied => return .AccessDenied,
154 error.OutOfMemory => return .OutOfMemory,
155 error.Unexpected => return .Unexpected,
156 error.InputOutput => return .FileSystem,
157 };
158 return .None;
159}
160
161// TODO: just use the actual self-hosted zig fmt. Until https://github.com/ziglang/zig/issues/2377,
162// we use a blocking implementation.
163export fn stage2_fmt(argc: c_int, argv: [*]const [*:0]const u8) c_int {
164 if (std.debug.runtime_safety) {
165 fmtMain(argc, argv) catch unreachable;
166 } else {
167 fmtMain(argc, argv) catch |e| {
168 std.debug.warn("{}\n", .{@errorName(e)});
169 return -1;
170 };
171 }
172 return 0;
173}
174
175fn fmtMain(argc: c_int, argv: [*]const [*:0]const u8) !void {
176 const allocator = std.heap.c_allocator;
177 var args_list = std.ArrayList([]const u8).init(allocator);
178 const argc_usize = @intCast(usize, argc);
179 var arg_i: usize = 0;
180 while (arg_i < argc_usize) : (arg_i += 1) {
181 try args_list.append(mem.toSliceConst(u8, argv[arg_i]));
182 }
183
184 stdout = &std.io.getStdOut().outStream().stream;
185 stderr_file = std.io.getStdErr();
186 stderr = &stderr_file.outStream().stream;
187
188 const args = args_list.toSliceConst()[2..];
189
190 var color: errmsg.Color = .Auto;
191 var stdin_flag: bool = false;
192 var check_flag: bool = false;
193 var input_files = ArrayList([]const u8).init(allocator);
194
195 {
196 var i: usize = 0;
197 while (i < args.len) : (i += 1) {
198 const arg = args[i];
199 if (mem.startsWith(u8, arg, "-")) {
200 if (mem.eql(u8, arg, "--help")) {
201 try stdout.write(self_hosted_main.usage_fmt);
202 process.exit(0);
203 } else if (mem.eql(u8, arg, "--color")) {
204 if (i + 1 >= args.len) {
205 try stderr.write("expected [auto|on|off] after --color\n");
206 process.exit(1);
207 }
208 i += 1;
209 const next_arg = args[i];
210 if (mem.eql(u8, next_arg, "auto")) {
211 color = .Auto;
212 } else if (mem.eql(u8, next_arg, "on")) {
213 color = .On;
214 } else if (mem.eql(u8, next_arg, "off")) {
215 color = .Off;
216 } else {
217 try stderr.print("expected [auto|on|off] after --color, found '{}'\n", .{next_arg});
218 process.exit(1);
219 }
220 } else if (mem.eql(u8, arg, "--stdin")) {
221 stdin_flag = true;
222 } else if (mem.eql(u8, arg, "--check")) {
223 check_flag = true;
224 } else {
225 try stderr.print("unrecognized parameter: '{}'", .{arg});
226 process.exit(1);
227 }
228 } else {
229 try input_files.append(arg);
230 }
231 }
232 }
233
234 if (stdin_flag) {
235 if (input_files.len != 0) {
236 try stderr.write("cannot use --stdin with positional arguments\n");
237 process.exit(1);
238 }
239
240 const stdin_file = io.getStdIn();
241 var stdin = stdin_file.inStream();
242
243 const source_code = try stdin.stream.readAllAlloc(allocator, self_hosted_main.max_src_size);
244 defer allocator.free(source_code);
245
246 const tree = std.zig.parse(allocator, source_code) catch |err| {
247 try stderr.print("error parsing stdin: {}\n", .{err});
248 process.exit(1);
249 };
250 defer tree.deinit();
251
252 var error_it = tree.errors.iterator(0);
253 while (error_it.next()) |parse_error| {
254 try printErrMsgToFile(allocator, parse_error, tree, "<stdin>", stderr_file, color);
255 }
256 if (tree.errors.len != 0) {
257 process.exit(1);
258 }
259 if (check_flag) {
260 const anything_changed = try std.zig.render(allocator, io.null_out_stream, tree);
261 const code = if (anything_changed) @as(u8, 1) else @as(u8, 0);
262 process.exit(code);
263 }
264
265 _ = try std.zig.render(allocator, stdout, tree);
266 return;
267 }
268
269 if (input_files.len == 0) {
270 try stderr.write("expected at least one source file argument\n");
271 process.exit(1);
272 }
273
274 var fmt = Fmt{
275 .seen = Fmt.SeenMap.init(allocator),
276 .any_error = false,
277 .color = color,
278 .allocator = allocator,
279 };
280
281 for (input_files.toSliceConst()) |file_path| {
282 try fmtPath(&fmt, file_path, check_flag);
283 }
284 if (fmt.any_error) {
285 process.exit(1);
286 }
287}
288
289const FmtError = error{
290 SystemResources,
291 OperationAborted,
292 IoPending,
293 BrokenPipe,
294 Unexpected,
295 WouldBlock,
296 FileClosed,
297 DestinationAddressRequired,
298 DiskQuota,
299 FileTooBig,
300 InputOutput,
301 NoSpaceLeft,
302 AccessDenied,
303 OutOfMemory,
304 RenameAcrossMountPoints,
305 ReadOnlyFileSystem,
306 LinkQuotaExceeded,
307 FileBusy,
308} || fs.File.OpenError;
309
310fn fmtPath(fmt: *Fmt, file_path: []const u8, check_mode: bool) FmtError!void {
311 if (fmt.seen.exists(file_path)) return;
312 try fmt.seen.put(file_path);
313
314 const source_code = io.readFileAlloc(fmt.allocator, file_path) catch |err| switch (err) {
315 error.IsDir, error.AccessDenied => {
316 // TODO make event based (and dir.next())
317 var dir = try fs.cwd().openDirList(file_path);
318 defer dir.close();
319
320 var dir_it = dir.iterate();
321
322 while (try dir_it.next()) |entry| {
323 if (entry.kind == .Directory or mem.endsWith(u8, entry.name, ".zig")) {
324 const full_path = try fs.path.join(fmt.allocator, &[_][]const u8{ file_path, entry.name });
325 try fmtPath(fmt, full_path, check_mode);
326 }
327 }
328 return;
329 },
330 else => {
331 // TODO lock stderr printing
332 try stderr.print("unable to open '{}': {}\n", .{ file_path, err });
333 fmt.any_error = true;
334 return;
335 },
336 };
337 defer fmt.allocator.free(source_code);
338
339 const tree = std.zig.parse(fmt.allocator, source_code) catch |err| {
340 try stderr.print("error parsing file '{}': {}\n", .{ file_path, err });
341 fmt.any_error = true;
342 return;
343 };
344 defer tree.deinit();
345
346 var error_it = tree.errors.iterator(0);
347 while (error_it.next()) |parse_error| {
348 try printErrMsgToFile(fmt.allocator, parse_error, tree, file_path, stderr_file, fmt.color);
349 }
350 if (tree.errors.len != 0) {
351 fmt.any_error = true;
352 return;
353 }
354
355 if (check_mode) {
356 const anything_changed = try std.zig.render(fmt.allocator, io.null_out_stream, tree);
357 if (anything_changed) {
358 try stderr.print("{}\n", .{file_path});
359 fmt.any_error = true;
360 }
361 } else {
362 const baf = try io.BufferedAtomicFile.create(fmt.allocator, file_path);
363 defer baf.destroy();
364
365 const anything_changed = try std.zig.render(fmt.allocator, baf.stream(), tree);
366 if (anything_changed) {
367 try stderr.print("{}\n", .{file_path});
368 try baf.finish();
369 }
370 }
371}
372
373const Fmt = struct {
374 seen: SeenMap,
375 any_error: bool,
376 color: errmsg.Color,
377 allocator: *mem.Allocator,
378
379 const SeenMap = std.BufSet;
380};
381
382fn printErrMsgToFile(
383 allocator: *mem.Allocator,
384 parse_error: *const ast.Error,
385 tree: *ast.Tree,
386 path: []const u8,
387 file: fs.File,
388 color: errmsg.Color,
389) !void {
390 const color_on = switch (color) {
391 .Auto => file.isTty(),
392 .On => true,
393 .Off => false,
394 };
395 const lok_token = parse_error.loc();
396 const span = errmsg.Span{
397 .first = lok_token,
398 .last = lok_token,
399 };
400
401 const first_token = tree.tokens.at(span.first);
402 const last_token = tree.tokens.at(span.last);
403 const start_loc = tree.tokenLocationPtr(0, first_token);
404 const end_loc = tree.tokenLocationPtr(first_token.end, last_token);
405
406 var text_buf = try std.Buffer.initSize(allocator, 0);
407 var out_stream = &std.io.BufferOutStream.init(&text_buf).stream;
408 try parse_error.render(&tree.tokens, out_stream);
409 const text = text_buf.toOwnedSlice();
410
411 const stream = &file.outStream().stream;
412 try stream.print("{}:{}:{}: error: {}\n", .{ path, start_loc.line + 1, start_loc.column + 1, text });
413
414 if (!color_on) return;
415
416 // Print \r and \t as one space each so that column counts line up
417 for (tree.source[start_loc.line_start..start_loc.line_end]) |byte| {
418 try stream.writeByte(switch (byte) {
419 '\r', '\t' => ' ',
420 else => byte,
421 });
422 }
423 try stream.writeByte('\n');
424 try stream.writeByteNTimes(' ', start_loc.column);
425 try stream.writeByteNTimes('~', last_token.end - first_token.start);
426 try stream.writeByte('\n');
427}
428
429export fn stage2_DepTokenizer_init(input: [*]const u8, len: usize) stage2_DepTokenizer {
430 const t = std.heap.c_allocator.create(DepTokenizer) catch @panic("failed to create .d tokenizer");
431 t.* = DepTokenizer.init(std.heap.c_allocator, input[0..len]);
432 return stage2_DepTokenizer{
433 .handle = t,
434 };
435}
436
437export fn stage2_DepTokenizer_deinit(self: *stage2_DepTokenizer) void {
438 self.handle.deinit();
439}
440
441export fn stage2_DepTokenizer_next(self: *stage2_DepTokenizer) stage2_DepNextResult {
442 const otoken = self.handle.next() catch {
443 const textz = std.Buffer.init(&self.handle.arena.allocator, self.handle.error_text) catch @panic("failed to create .d tokenizer error text");
444 return stage2_DepNextResult{
445 .type_id = .error_,
446 .textz = textz.toSlice().ptr,
447 };
448 };
449 const token = otoken orelse {
450 return stage2_DepNextResult{
451 .type_id = .null_,
452 .textz = undefined,
453 };
454 };
455 const textz = std.Buffer.init(&self.handle.arena.allocator, token.bytes) catch @panic("failed to create .d tokenizer token text");
456 return stage2_DepNextResult{
457 .type_id = switch (token.id) {
458 .target => .target,
459 .prereq => .prereq,
460 },
461 .textz = textz.toSlice().ptr,
462 };
463}
464
465const stage2_DepTokenizer = extern struct {
466 handle: *DepTokenizer,
467};
468
469const stage2_DepNextResult = extern struct {
470 type_id: TypeId,
471
472 // when type_id == error --> error text
473 // when type_id == null --> undefined
474 // when type_id == target --> target pathname
475 // when type_id == prereq --> prereq pathname
476 textz: [*]const u8,
477
478 const TypeId = extern enum {
479 error_,
480 null_,
481 target,
482 prereq,
483 };
484};
485
486// ABI warning
487export fn stage2_attach_segfault_handler() void {
488 if (std.debug.runtime_safety and std.debug.have_segfault_handling_support) {
489 std.debug.attachSegfaultHandler();
490 }
491}
492
493// ABI warning
494export fn stage2_progress_create() *std.Progress {
495 const ptr = std.heap.c_allocator.create(std.Progress) catch @panic("out of memory");
496 ptr.* = std.Progress{};
497 return ptr;
498}
499
500// ABI warning
501export fn stage2_progress_destroy(progress: *std.Progress) void {
502 std.heap.c_allocator.destroy(progress);
503}
504
505// ABI warning
506export fn stage2_progress_start_root(
507 progress: *std.Progress,
508 name_ptr: [*]const u8,
509 name_len: usize,
510 estimated_total_items: usize,
511) *std.Progress.Node {
512 return progress.start(
513 name_ptr[0..name_len],
514 if (estimated_total_items == 0) null else estimated_total_items,
515 ) catch @panic("timer unsupported");
516}
517
518// ABI warning
519export fn stage2_progress_disable_tty(progress: *std.Progress) void {
520 progress.terminal = null;
521}
522
523// ABI warning
524export fn stage2_progress_start(
525 node: *std.Progress.Node,
526 name_ptr: [*]const u8,
527 name_len: usize,
528 estimated_total_items: usize,
529) *std.Progress.Node {
530 const child_node = std.heap.c_allocator.create(std.Progress.Node) catch @panic("out of memory");
531 child_node.* = node.start(
532 name_ptr[0..name_len],
533 if (estimated_total_items == 0) null else estimated_total_items,
534 );
535 child_node.activate();
536 return child_node;
537}
538
539// ABI warning
540export fn stage2_progress_end(node: *std.Progress.Node) void {
541 node.end();
542 if (&node.context.root != node) {
543 std.heap.c_allocator.destroy(node);
544 }
545}
546
547// ABI warning
548export fn stage2_progress_complete_one(node: *std.Progress.Node) void {
549 node.completeOne();
550}
551
552// ABI warning
553export fn stage2_progress_update_node(node: *std.Progress.Node, done_count: usize, total_count: usize) void {
554 node.completed_items = done_count;
555 node.estimated_total_items = total_count;
556 node.activate();
557 node.context.maybeRefresh();
558}
559
560fn cpuFeaturesFromLLVM(
561 arch: Target.Arch,
562 llvm_cpu_name_z: ?[*:0]const u8,
563 llvm_cpu_features_opt: ?[*:0]const u8,
564) !Target.CpuFeatures {
565 var result = arch.getBaselineCpuFeatures();
566
567 if (llvm_cpu_name_z) |cpu_name_z| {
568 const llvm_cpu_name = mem.toSliceConst(u8, cpu_name_z);
569
570 for (arch.allCpus()) |cpu| {
571 const this_llvm_name = cpu.llvm_name orelse continue;
572 if (mem.eql(u8, this_llvm_name, llvm_cpu_name)) {
573 // Here we use the non-dependencies-populated set,
574 // so that subtracting features later in this function
575 // affect the prepopulated set.
576 result = Target.CpuFeatures{
577 .cpu = cpu,
578 .features = cpu.features,
579 };
580 break;
581 }
582 }
583 }
584
585 const all_features = arch.allFeaturesList();
586
587 if (llvm_cpu_features_opt) |llvm_cpu_features| {
588 var it = mem.tokenize(mem.toSliceConst(u8, llvm_cpu_features), ",");
589 while (it.next()) |decorated_llvm_feat| {
590 var op: enum {
591 add,
592 sub,
593 } = undefined;
594 var llvm_feat: []const u8 = undefined;
595 if (mem.startsWith(u8, decorated_llvm_feat, "+")) {
596 op = .add;
597 llvm_feat = decorated_llvm_feat[1..];
598 } else if (mem.startsWith(u8, decorated_llvm_feat, "-")) {
599 op = .sub;
600 llvm_feat = decorated_llvm_feat[1..];
601 } else {
602 return error.InvalidLlvmCpuFeaturesFormat;
603 }
604 for (all_features) |feature, index_usize| {
605 const this_llvm_name = feature.llvm_name orelse continue;
606 if (mem.eql(u8, llvm_feat, this_llvm_name)) {
607 const index = @intCast(Target.Cpu.Feature.Set.Index, index_usize);
608 switch (op) {
609 .add => result.features.addFeature(index),
610 .sub => result.features.removeFeature(index),
611 }
612 break;
613 }
614 }
615 }
616 }
617
618 result.features.populateDependencies(all_features);
619 return result;
620}
621
622// ABI warning
623export fn stage2_cmd_targets(zig_triple: [*:0]const u8) c_int {
624 cmdTargets(zig_triple) catch |err| {
625 std.debug.warn("unable to list targets: {}\n", .{@errorName(err)});
626 return -1;
627 };
628 return 0;
629}
630
631fn cmdTargets(zig_triple: [*:0]const u8) !void {
632 var target = try Target.parse(mem.toSliceConst(u8, zig_triple));
633 target.Cross.cpu_features = blk: {
634 const llvm = @import("llvm.zig");
635 const llvm_cpu_name = llvm.GetHostCPUName();
636 const llvm_cpu_features = llvm.GetNativeFeatures();
637 break :blk try cpuFeaturesFromLLVM(target.Cross.arch, llvm_cpu_name, llvm_cpu_features);
638 };
639 return @import("print_targets.zig").cmdTargets(
640 std.heap.c_allocator,
641 &[0][]u8{},
642 &std.io.getStdOut().outStream().stream,
643 target,
644 );
645}
646
647const Stage2CpuFeatures = struct {
648 allocator: *mem.Allocator,
649 cpu_features: Target.CpuFeatures,
650
651 llvm_features_str: ?[*:0]const u8,
652
653 builtin_str: [:0]const u8,
654 cache_hash: [:0]const u8,
655
656 const Self = @This();
657
658 fn createFromNative(allocator: *mem.Allocator) !*Self {
659 const arch = Target.current.getArch();
660 const llvm = @import("llvm.zig");
661 const llvm_cpu_name = llvm.GetHostCPUName();
662 const llvm_cpu_features = llvm.GetNativeFeatures();
663 const cpu_features = try cpuFeaturesFromLLVM(arch, llvm_cpu_name, llvm_cpu_features);
664 return createFromCpuFeatures(allocator, arch, cpu_features);
665 }
666
667 fn createFromCpuFeatures(
668 allocator: *mem.Allocator,
669 arch: Target.Arch,
670 cpu_features: Target.CpuFeatures,
671 ) !*Self {
672 const self = try allocator.create(Self);
673 errdefer allocator.destroy(self);
674
675 const cache_hash = try std.fmt.allocPrint0(allocator, "{}\n{}", .{
676 cpu_features.cpu.name,
677 cpu_features.features.asBytes(),
678 });
679 errdefer allocator.free(cache_hash);
680
681 const generic_arch_name = arch.genericName();
682 var builtin_str_buffer = try std.Buffer.allocPrint(allocator,
683 \\CpuFeatures{{
684 \\ .cpu = &Target.{}.cpu.{},
685 \\ .features = Target.{}.featureSet(&[_]Target.{}.Feature{{
686 \\
687 , .{
688 generic_arch_name,
689 cpu_features.cpu.name,
690 generic_arch_name,
691 generic_arch_name,
692 });
693 defer builtin_str_buffer.deinit();
694
695 var llvm_features_buffer = try std.Buffer.initSize(allocator, 0);
696 defer llvm_features_buffer.deinit();
697
698 for (arch.allFeaturesList()) |feature, index_usize| {
699 const index = @intCast(Target.Cpu.Feature.Set.Index, index_usize);
700 const is_enabled = cpu_features.features.isEnabled(index);
701
702 if (feature.llvm_name) |llvm_name| {
703 const plus_or_minus = "-+"[@boolToInt(is_enabled)];
704 try llvm_features_buffer.appendByte(plus_or_minus);
705 try llvm_features_buffer.append(llvm_name);
706 try llvm_features_buffer.append(",");
707 }
708
709 if (is_enabled) {
710 // TODO some kind of "zig identifier escape" function rather than
711 // unconditionally using @"" syntax
712 try builtin_str_buffer.append(" .@\"");
713 try builtin_str_buffer.append(feature.name);
714 try builtin_str_buffer.append("\",\n");
715 }
716 }
717
718 try builtin_str_buffer.append(
719 \\ }),
720 \\};
721 \\
722 );
723
724 assert(mem.endsWith(u8, llvm_features_buffer.toSliceConst(), ","));
725 llvm_features_buffer.shrink(llvm_features_buffer.len() - 1);
726
727 self.* = Self{
728 .allocator = allocator,
729 .cpu_features = cpu_features,
730 .llvm_features_str = llvm_features_buffer.toOwnedSlice().ptr,
731 .builtin_str = builtin_str_buffer.toOwnedSlice(),
732 .cache_hash = cache_hash,
733 };
734 return self;
735 }
736
737 fn destroy(self: *Self) void {
738 self.allocator.free(self.cache_hash);
739 self.allocator.free(self.builtin_str);
740 // TODO if (self.llvm_features_str) |llvm_features_str| self.allocator.free(llvm_features_str);
741 self.allocator.destroy(self);
742 }
743};
744
745// ABI warning
746export fn stage2_cpu_features_parse(
747 result: **Stage2CpuFeatures,
748 zig_triple: ?[*:0]const u8,
749 cpu_name: ?[*:0]const u8,
750 cpu_features: ?[*:0]const u8,
751) Error {
752 result.* = stage2ParseCpuFeatures(zig_triple, cpu_name, cpu_features) catch |err| switch (err) {
753 error.OutOfMemory => return .OutOfMemory,
754 error.UnknownArchitecture => return .UnknownArchitecture,
755 error.UnknownSubArchitecture => return .UnknownSubArchitecture,
756 error.UnknownOperatingSystem => return .UnknownOperatingSystem,
757 error.UnknownApplicationBinaryInterface => return .UnknownApplicationBinaryInterface,
758 error.MissingOperatingSystem => return .MissingOperatingSystem,
759 error.MissingArchitecture => return .MissingArchitecture,
760 error.InvalidLlvmCpuFeaturesFormat => return .InvalidLlvmCpuFeaturesFormat,
761 error.InvalidCpuFeatures => return .InvalidCpuFeatures,
762 };
763 return .None;
764}
765
766fn stage2ParseCpuFeatures(
767 zig_triple_oz: ?[*:0]const u8,
768 cpu_name_oz: ?[*:0]const u8,
769 cpu_features_oz: ?[*:0]const u8,
770) !*Stage2CpuFeatures {
771 const zig_triple_z = zig_triple_oz orelse return Stage2CpuFeatures.createFromNative(std.heap.c_allocator);
772 const target = try Target.parse(mem.toSliceConst(u8, zig_triple_z));
773 const arch = target.Cross.arch;
774
775 const cpu = if (cpu_name_oz) |cpu_name_z| blk: {
776 const cpu_name = mem.toSliceConst(u8, cpu_name_z);
777 break :blk arch.parseCpu(cpu_name) catch |err| switch (err) {
778 error.UnknownCpu => {
779 std.debug.warn("Unknown CPU: '{}'\nAvailable CPUs for architecture '{}':\n", .{
780 cpu_name,
781 @tagName(arch),
782 });
783 for (arch.allCpus()) |cpu| {
784 std.debug.warn(" {}\n", .{cpu.name});
785 }
786 process.exit(1);
787 },
788 else => |e| return e,
789 };
790 } else target.Cross.cpu_features.cpu;
791
792 var set = if (cpu_features_oz) |cpu_features_z| blk: {
793 const cpu_features = mem.toSliceConst(u8, cpu_features_z);
794 break :blk arch.parseCpuFeatureSet(cpu, cpu_features) catch |err| switch (err) {
795 error.UnknownCpuFeature => {
796 std.debug.warn(
797 \\Unknown CPU features specified.
798 \\Available CPU features for architecture '{}':
799 \\
800 , .{@tagName(arch)});
801 for (arch.allFeaturesList()) |feature| {
802 std.debug.warn(" {}\n", .{feature.name});
803 }
804 process.exit(1);
805 },
806 else => |e| return e,
807 };
808 } else cpu.features;
809
810 if (arch.subArchFeature()) |index| {
811 set.addFeature(index);
812 }
813 set.populateDependencies(arch.allFeaturesList());
814
815 return Stage2CpuFeatures.createFromCpuFeatures(std.heap.c_allocator, arch, .{
816 .cpu = cpu,
817 .features = set,
818 });
819}
820
821// ABI warning
822export fn stage2_cpu_features_get_cache_hash(
823 cpu_features: *const Stage2CpuFeatures,
824 ptr: *[*:0]const u8,
825 len: *usize,
826) void {
827 ptr.* = cpu_features.cache_hash.ptr;
828 len.* = cpu_features.cache_hash.len;
829}
830
831// ABI warning
832export fn stage2_cpu_features_get_builtin_str(
833 cpu_features: *const Stage2CpuFeatures,
834 ptr: *[*:0]const u8,
835 len: *usize,
836) void {
837 ptr.* = cpu_features.builtin_str.ptr;
838 len.* = cpu_features.builtin_str.len;
839}
840
841// ABI warning
842export fn stage2_cpu_features_get_llvm_cpu(cpu_features: *const Stage2CpuFeatures) ?[*:0]const u8 {
843 return if (cpu_features.cpu_features.cpu.llvm_name) |s| s.ptr else null;
844}
845
846// ABI warning
847export fn stage2_cpu_features_get_llvm_features(cpu_features: *const Stage2CpuFeatures) ?[*:0]const u8 {
848 return cpu_features.llvm_features_str;
849}
850
851// ABI warning
852const Stage2LibCInstallation = extern struct {
853 include_dir: [*:0]const u8,
854 include_dir_len: usize,
855 sys_include_dir: [*:0]const u8,
856 sys_include_dir_len: usize,
857 crt_dir: [*:0]const u8,
858 crt_dir_len: usize,
859 static_crt_dir: [*:0]const u8,
860 static_crt_dir_len: usize,
861 msvc_lib_dir: [*:0]const u8,
862 msvc_lib_dir_len: usize,
863 kernel32_lib_dir: [*:0]const u8,
864 kernel32_lib_dir_len: usize,
865
866 fn initFromStage2(self: *Stage2LibCInstallation, libc: LibCInstallation) void {
867 if (libc.include_dir) |s| {
868 self.include_dir = s.ptr;
869 self.include_dir_len = s.len;
870 } else {
871 self.include_dir = "";
872 self.include_dir_len = 0;
873 }
874 if (libc.sys_include_dir) |s| {
875 self.sys_include_dir = s.ptr;
876 self.sys_include_dir_len = s.len;
877 } else {
878 self.sys_include_dir = "";
879 self.sys_include_dir_len = 0;
880 }
881 if (libc.crt_dir) |s| {
882 self.crt_dir = s.ptr;
883 self.crt_dir_len = s.len;
884 } else {
885 self.crt_dir = "";
886 self.crt_dir_len = 0;
887 }
888 if (libc.static_crt_dir) |s| {
889 self.static_crt_dir = s.ptr;
890 self.static_crt_dir_len = s.len;
891 } else {
892 self.static_crt_dir = "";
893 self.static_crt_dir_len = 0;
894 }
895 if (libc.msvc_lib_dir) |s| {
896 self.msvc_lib_dir = s.ptr;
897 self.msvc_lib_dir_len = s.len;
898 } else {
899 self.msvc_lib_dir = "";
900 self.msvc_lib_dir_len = 0;
901 }
902 if (libc.kernel32_lib_dir) |s| {
903 self.kernel32_lib_dir = s.ptr;
904 self.kernel32_lib_dir_len = s.len;
905 } else {
906 self.kernel32_lib_dir = "";
907 self.kernel32_lib_dir_len = 0;
908 }
909 }
910
911 fn toStage2(self: Stage2LibCInstallation) LibCInstallation {
912 var libc: LibCInstallation = .{};
913 if (self.include_dir_len != 0) {
914 libc.include_dir = self.include_dir[0..self.include_dir_len :0];
915 }
916 if (self.sys_include_dir_len != 0) {
917 libc.sys_include_dir = self.sys_include_dir[0..self.sys_include_dir_len :0];
918 }
919 if (self.crt_dir_len != 0) {
920 libc.crt_dir = self.crt_dir[0..self.crt_dir_len :0];
921 }
922 if (self.static_crt_dir_len != 0) {
923 libc.static_crt_dir = self.static_crt_dir[0..self.static_crt_dir_len :0];
924 }
925 if (self.msvc_lib_dir_len != 0) {
926 libc.msvc_lib_dir = self.msvc_lib_dir[0..self.msvc_lib_dir_len :0];
927 }
928 if (self.kernel32_lib_dir_len != 0) {
929 libc.kernel32_lib_dir = self.kernel32_lib_dir[0..self.kernel32_lib_dir_len :0];
930 }
931 return libc;
932 }
933};
934
935// ABI warning
936export fn stage2_libc_parse(stage1_libc: *Stage2LibCInstallation, libc_file_z: [*:0]const u8) Error {
937 stderr_file = std.io.getStdErr();
938 stderr = &stderr_file.outStream().stream;
939 const libc_file = mem.toSliceConst(u8, libc_file_z);
940 var libc = LibCInstallation.parse(std.heap.c_allocator, libc_file, stderr) catch |err| switch (err) {
941 error.ParseError => return .SemanticAnalyzeFail,
942 error.DiskQuota => return .DiskQuota,
943 error.FileTooBig => return .FileTooBig,
944 error.InputOutput => return .FileSystem,
945 error.NoSpaceLeft => return .NoSpaceLeft,
946 error.AccessDenied => return .AccessDenied,
947 error.BrokenPipe => return .BrokenPipe,
948 error.SystemResources => return .SystemResources,
949 error.OperationAborted => return .OperationAborted,
950 error.WouldBlock => unreachable,
951 error.Unexpected => return .Unexpected,
952 error.EndOfStream => return .EndOfFile,
953 error.IsDir => return .IsDir,
954 error.ConnectionResetByPeer => unreachable,
955 error.OutOfMemory => return .OutOfMemory,
956 error.Unseekable => unreachable,
957 error.SharingViolation => return .SharingViolation,
958 error.PathAlreadyExists => unreachable,
959 error.FileNotFound => return .FileNotFound,
960 error.PipeBusy => return .PipeBusy,
961 error.NameTooLong => return .PathTooLong,
962 error.InvalidUtf8 => return .BadPathName,
963 error.BadPathName => return .BadPathName,
964 error.SymLinkLoop => return .SymLinkLoop,
965 error.ProcessFdQuotaExceeded => return .ProcessFdQuotaExceeded,
966 error.SystemFdQuotaExceeded => return .SystemFdQuotaExceeded,
967 error.NoDevice => return .NoDevice,
968 error.NotDir => return .NotDir,
969 error.DeviceBusy => return .DeviceBusy,
970 };
971 stage1_libc.initFromStage2(libc);
972 return .None;
973}
974
975// ABI warning
976export fn stage2_libc_find_native(stage1_libc: *Stage2LibCInstallation) Error {
977 var libc = LibCInstallation.findNative(std.heap.c_allocator) catch |err| switch (err) {
978 error.OutOfMemory => return .OutOfMemory,
979 error.FileSystem => return .FileSystem,
980 error.UnableToSpawnCCompiler => return .UnableToSpawnCCompiler,
981 error.CCompilerExitCode => return .CCompilerExitCode,
982 error.CCompilerCrashed => return .CCompilerCrashed,
983 error.CCompilerCannotFindHeaders => return .CCompilerCannotFindHeaders,
984 error.LibCRuntimeNotFound => return .LibCRuntimeNotFound,
985 error.LibCStdLibHeaderNotFound => return .LibCStdLibHeaderNotFound,
986 error.LibCKernel32LibNotFound => return .LibCKernel32LibNotFound,
987 error.UnsupportedArchitecture => return .UnsupportedArchitecture,
988 };
989 stage1_libc.initFromStage2(libc);
990 return .None;
991}
992
993// ABI warning
994export fn stage2_libc_render(stage1_libc: *Stage2LibCInstallation, output_file: *FILE) Error {
995 var libc = stage1_libc.toStage2();
996 const c_out_stream = &std.io.COutStream.init(output_file).stream;
997 libc.render(c_out_stream) catch |err| switch (err) {
998 error.WouldBlock => unreachable, // stage1 opens stuff in exclusively blocking mode
999 error.SystemResources => return .SystemResources,
1000 error.OperationAborted => return .OperationAborted,
1001 error.BrokenPipe => return .BrokenPipe,
1002 error.DiskQuota => return .DiskQuota,
1003 error.FileTooBig => return .FileTooBig,
1004 error.NoSpaceLeft => return .NoSpaceLeft,
1005 error.AccessDenied => return .AccessDenied,
1006 error.Unexpected => return .Unexpected,
1007 error.InputOutput => return .FileSystem,
1008 };
1009 return .None;
1010}
1011
1012// ABI warning
1013export fn stage2_libc_cc_print_file_name(
1014 out_ptr: *[*:0]u8,
1015 out_len: *usize,
1016 o_file: [*:0]const u8,
1017 want_dirname: bool,
1018) Error {
1019 const result = @import("libc_installation.zig").ccPrintFileName(
1020 std.heap.c_allocator,
1021 mem.toSliceConst(u8, o_file),
1022 if (want_dirname) .only_dir else .full_path,
1023 ) catch |err| switch (err) {
1024 error.OutOfMemory => return .OutOfMemory,
1025 error.LibCRuntimeNotFound => return .FileNotFound,
1026 error.CCompilerExitCode => return .CCompilerExitCode,
1027 error.CCompilerCrashed => return .CCompilerCrashed,
1028 error.UnableToSpawnCCompiler => return .UnableToSpawnCCompiler,
1029 };
1030 out_ptr.* = result.ptr;
1031 out_len.* = result.len;
1032 return .None;
1033}
src-self-hosted/stage2.zig created+1033
......@@ -0,0 +1,1033 @@
1// This is Zig code that is used by both stage1 and stage2.
2// The prototypes in src/userland.h must match these definitions.
3
4const std = @import("std");
5const io = std.io;
6const mem = std.mem;
7const fs = std.fs;
8const process = std.process;
9const Allocator = mem.Allocator;
10const ArrayList = std.ArrayList;
11const Buffer = std.Buffer;
12const Target = std.Target;
13const self_hosted_main = @import("main.zig");
14const errmsg = @import("errmsg.zig");
15const DepTokenizer = @import("dep_tokenizer.zig").Tokenizer;
16const assert = std.debug.assert;
17const LibCInstallation = @import("libc_installation.zig").LibCInstallation;
18
19var stderr_file: fs.File = undefined;
20var stderr: *io.OutStream(fs.File.WriteError) = undefined;
21var stdout: *io.OutStream(fs.File.WriteError) = undefined;
22
23comptime {
24 _ = @import("dep_tokenizer.zig");
25}
26
27// ABI warning
28export fn stage2_zen(ptr: *[*]const u8, len: *usize) void {
29 const info_zen = @import("main.zig").info_zen;
30 ptr.* = info_zen;
31 len.* = info_zen.len;
32}
33
34// ABI warning
35export fn stage2_panic(ptr: [*]const u8, len: usize) void {
36 @panic(ptr[0..len]);
37}
38
39// ABI warning
40const Error = extern enum {
41 None,
42 OutOfMemory,
43 InvalidFormat,
44 SemanticAnalyzeFail,
45 AccessDenied,
46 Interrupted,
47 SystemResources,
48 FileNotFound,
49 FileSystem,
50 FileTooBig,
51 DivByZero,
52 Overflow,
53 PathAlreadyExists,
54 Unexpected,
55 ExactDivRemainder,
56 NegativeDenominator,
57 ShiftedOutOneBits,
58 CCompileErrors,
59 EndOfFile,
60 IsDir,
61 NotDir,
62 UnsupportedOperatingSystem,
63 SharingViolation,
64 PipeBusy,
65 PrimitiveTypeNotFound,
66 CacheUnavailable,
67 PathTooLong,
68 CCompilerCannotFindFile,
69 NoCCompilerInstalled,
70 ReadingDepFile,
71 InvalidDepFile,
72 MissingArchitecture,
73 MissingOperatingSystem,
74 UnknownArchitecture,
75 UnknownOperatingSystem,
76 UnknownABI,
77 InvalidFilename,
78 DiskQuota,
79 DiskSpace,
80 UnexpectedWriteFailure,
81 UnexpectedSeekFailure,
82 UnexpectedFileTruncationFailure,
83 Unimplemented,
84 OperationAborted,
85 BrokenPipe,
86 NoSpaceLeft,
87 NotLazy,
88 IsAsync,
89 ImportOutsidePkgPath,
90 UnknownCpu,
91 UnknownSubArchitecture,
92 UnknownCpuFeature,
93 InvalidCpuFeatures,
94 InvalidLlvmCpuFeaturesFormat,
95 UnknownApplicationBinaryInterface,
96 ASTUnitFailure,
97 BadPathName,
98 SymLinkLoop,
99 ProcessFdQuotaExceeded,
100 SystemFdQuotaExceeded,
101 NoDevice,
102 DeviceBusy,
103 UnableToSpawnCCompiler,
104 CCompilerExitCode,
105 CCompilerCrashed,
106 CCompilerCannotFindHeaders,
107 LibCRuntimeNotFound,
108 LibCStdLibHeaderNotFound,
109 LibCKernel32LibNotFound,
110 UnsupportedArchitecture,
111};
112
113const FILE = std.c.FILE;
114const ast = std.zig.ast;
115const translate_c = @import("translate_c.zig");
116
117/// Args should have a null terminating last arg.
118export fn stage2_translate_c(
119 out_ast: **ast.Tree,
120 out_errors_ptr: *[*]translate_c.ClangErrMsg,
121 out_errors_len: *usize,
122 args_begin: [*]?[*]const u8,
123 args_end: [*]?[*]const u8,
124 resources_path: [*:0]const u8,
125) Error {
126 var errors = @as([*]translate_c.ClangErrMsg, undefined)[0..0];
127 out_ast.* = translate_c.translate(std.heap.c_allocator, args_begin, args_end, &errors, resources_path) catch |err| switch (err) {
128 error.SemanticAnalyzeFail => {
129 out_errors_ptr.* = errors.ptr;
130 out_errors_len.* = errors.len;
131 return .CCompileErrors;
132 },
133 error.ASTUnitFailure => return .ASTUnitFailure,
134 error.OutOfMemory => return .OutOfMemory,
135 };
136 return .None;
137}
138
139export fn stage2_free_clang_errors(errors_ptr: [*]translate_c.ClangErrMsg, errors_len: usize) void {
140 translate_c.freeErrors(errors_ptr[0..errors_len]);
141}
142
143export fn stage2_render_ast(tree: *ast.Tree, output_file: *FILE) Error {
144 const c_out_stream = &std.io.COutStream.init(output_file).stream;
145 _ = std.zig.render(std.heap.c_allocator, c_out_stream, tree) catch |e| switch (e) {
146 error.WouldBlock => unreachable, // stage1 opens stuff in exclusively blocking mode
147 error.SystemResources => return .SystemResources,
148 error.OperationAborted => return .OperationAborted,
149 error.BrokenPipe => return .BrokenPipe,
150 error.DiskQuota => return .DiskQuota,
151 error.FileTooBig => return .FileTooBig,
152 error.NoSpaceLeft => return .NoSpaceLeft,
153 error.AccessDenied => return .AccessDenied,
154 error.OutOfMemory => return .OutOfMemory,
155 error.Unexpected => return .Unexpected,
156 error.InputOutput => return .FileSystem,
157 };
158 return .None;
159}
160
161// TODO: just use the actual self-hosted zig fmt. Until https://github.com/ziglang/zig/issues/2377,
162// we use a blocking implementation.
163export fn stage2_fmt(argc: c_int, argv: [*]const [*:0]const u8) c_int {
164 if (std.debug.runtime_safety) {
165 fmtMain(argc, argv) catch unreachable;
166 } else {
167 fmtMain(argc, argv) catch |e| {
168 std.debug.warn("{}\n", .{@errorName(e)});
169 return -1;
170 };
171 }
172 return 0;
173}
174
175fn fmtMain(argc: c_int, argv: [*]const [*:0]const u8) !void {
176 const allocator = std.heap.c_allocator;
177 var args_list = std.ArrayList([]const u8).init(allocator);
178 const argc_usize = @intCast(usize, argc);
179 var arg_i: usize = 0;
180 while (arg_i < argc_usize) : (arg_i += 1) {
181 try args_list.append(mem.toSliceConst(u8, argv[arg_i]));
182 }
183
184 stdout = &std.io.getStdOut().outStream().stream;
185 stderr_file = std.io.getStdErr();
186 stderr = &stderr_file.outStream().stream;
187
188 const args = args_list.toSliceConst()[2..];
189
190 var color: errmsg.Color = .Auto;
191 var stdin_flag: bool = false;
192 var check_flag: bool = false;
193 var input_files = ArrayList([]const u8).init(allocator);
194
195 {
196 var i: usize = 0;
197 while (i < args.len) : (i += 1) {
198 const arg = args[i];
199 if (mem.startsWith(u8, arg, "-")) {
200 if (mem.eql(u8, arg, "--help")) {
201 try stdout.write(self_hosted_main.usage_fmt);
202 process.exit(0);
203 } else if (mem.eql(u8, arg, "--color")) {
204 if (i + 1 >= args.len) {
205 try stderr.write("expected [auto|on|off] after --color\n");
206 process.exit(1);
207 }
208 i += 1;
209 const next_arg = args[i];
210 if (mem.eql(u8, next_arg, "auto")) {
211 color = .Auto;
212 } else if (mem.eql(u8, next_arg, "on")) {
213 color = .On;
214 } else if (mem.eql(u8, next_arg, "off")) {
215 color = .Off;
216 } else {
217 try stderr.print("expected [auto|on|off] after --color, found '{}'\n", .{next_arg});
218 process.exit(1);
219 }
220 } else if (mem.eql(u8, arg, "--stdin")) {
221 stdin_flag = true;
222 } else if (mem.eql(u8, arg, "--check")) {
223 check_flag = true;
224 } else {
225 try stderr.print("unrecognized parameter: '{}'", .{arg});
226 process.exit(1);
227 }
228 } else {
229 try input_files.append(arg);
230 }
231 }
232 }
233
234 if (stdin_flag) {
235 if (input_files.len != 0) {
236 try stderr.write("cannot use --stdin with positional arguments\n");
237 process.exit(1);
238 }
239
240 const stdin_file = io.getStdIn();
241 var stdin = stdin_file.inStream();
242
243 const source_code = try stdin.stream.readAllAlloc(allocator, self_hosted_main.max_src_size);
244 defer allocator.free(source_code);
245
246 const tree = std.zig.parse(allocator, source_code) catch |err| {
247 try stderr.print("error parsing stdin: {}\n", .{err});
248 process.exit(1);
249 };
250 defer tree.deinit();
251
252 var error_it = tree.errors.iterator(0);
253 while (error_it.next()) |parse_error| {
254 try printErrMsgToFile(allocator, parse_error, tree, "<stdin>", stderr_file, color);
255 }
256 if (tree.errors.len != 0) {
257 process.exit(1);
258 }
259 if (check_flag) {
260 const anything_changed = try std.zig.render(allocator, io.null_out_stream, tree);
261 const code = if (anything_changed) @as(u8, 1) else @as(u8, 0);
262 process.exit(code);
263 }
264
265 _ = try std.zig.render(allocator, stdout, tree);
266 return;
267 }
268
269 if (input_files.len == 0) {
270 try stderr.write("expected at least one source file argument\n");
271 process.exit(1);
272 }
273
274 var fmt = Fmt{
275 .seen = Fmt.SeenMap.init(allocator),
276 .any_error = false,
277 .color = color,
278 .allocator = allocator,
279 };
280
281 for (input_files.toSliceConst()) |file_path| {
282 try fmtPath(&fmt, file_path, check_flag);
283 }
284 if (fmt.any_error) {
285 process.exit(1);
286 }
287}
288
289const FmtError = error{
290 SystemResources,
291 OperationAborted,
292 IoPending,
293 BrokenPipe,
294 Unexpected,
295 WouldBlock,
296 FileClosed,
297 DestinationAddressRequired,
298 DiskQuota,
299 FileTooBig,
300 InputOutput,
301 NoSpaceLeft,
302 AccessDenied,
303 OutOfMemory,
304 RenameAcrossMountPoints,
305 ReadOnlyFileSystem,
306 LinkQuotaExceeded,
307 FileBusy,
308} || fs.File.OpenError;
309
310fn fmtPath(fmt: *Fmt, file_path: []const u8, check_mode: bool) FmtError!void {
311 if (fmt.seen.exists(file_path)) return;
312 try fmt.seen.put(file_path);
313
314 const source_code = io.readFileAlloc(fmt.allocator, file_path) catch |err| switch (err) {
315 error.IsDir, error.AccessDenied => {
316 // TODO make event based (and dir.next())
317 var dir = try fs.cwd().openDirList(file_path);
318 defer dir.close();
319
320 var dir_it = dir.iterate();
321
322 while (try dir_it.next()) |entry| {
323 if (entry.kind == .Directory or mem.endsWith(u8, entry.name, ".zig")) {
324 const full_path = try fs.path.join(fmt.allocator, &[_][]const u8{ file_path, entry.name });
325 try fmtPath(fmt, full_path, check_mode);
326 }
327 }
328 return;
329 },
330 else => {
331 // TODO lock stderr printing
332 try stderr.print("unable to open '{}': {}\n", .{ file_path, err });
333 fmt.any_error = true;
334 return;
335 },
336 };
337 defer fmt.allocator.free(source_code);
338
339 const tree = std.zig.parse(fmt.allocator, source_code) catch |err| {
340 try stderr.print("error parsing file '{}': {}\n", .{ file_path, err });
341 fmt.any_error = true;
342 return;
343 };
344 defer tree.deinit();
345
346 var error_it = tree.errors.iterator(0);
347 while (error_it.next()) |parse_error| {
348 try printErrMsgToFile(fmt.allocator, parse_error, tree, file_path, stderr_file, fmt.color);
349 }
350 if (tree.errors.len != 0) {
351 fmt.any_error = true;
352 return;
353 }
354
355 if (check_mode) {
356 const anything_changed = try std.zig.render(fmt.allocator, io.null_out_stream, tree);
357 if (anything_changed) {
358 try stderr.print("{}\n", .{file_path});
359 fmt.any_error = true;
360 }
361 } else {
362 const baf = try io.BufferedAtomicFile.create(fmt.allocator, file_path);
363 defer baf.destroy();
364
365 const anything_changed = try std.zig.render(fmt.allocator, baf.stream(), tree);
366 if (anything_changed) {
367 try stderr.print("{}\n", .{file_path});
368 try baf.finish();
369 }
370 }
371}
372
373const Fmt = struct {
374 seen: SeenMap,
375 any_error: bool,
376 color: errmsg.Color,
377 allocator: *mem.Allocator,
378
379 const SeenMap = std.BufSet;
380};
381
382fn printErrMsgToFile(
383 allocator: *mem.Allocator,
384 parse_error: *const ast.Error,
385 tree: *ast.Tree,
386 path: []const u8,
387 file: fs.File,
388 color: errmsg.Color,
389) !void {
390 const color_on = switch (color) {
391 .Auto => file.isTty(),
392 .On => true,
393 .Off => false,
394 };
395 const lok_token = parse_error.loc();
396 const span = errmsg.Span{
397 .first = lok_token,
398 .last = lok_token,
399 };
400
401 const first_token = tree.tokens.at(span.first);
402 const last_token = tree.tokens.at(span.last);
403 const start_loc = tree.tokenLocationPtr(0, first_token);
404 const end_loc = tree.tokenLocationPtr(first_token.end, last_token);
405
406 var text_buf = try std.Buffer.initSize(allocator, 0);
407 var out_stream = &std.io.BufferOutStream.init(&text_buf).stream;
408 try parse_error.render(&tree.tokens, out_stream);
409 const text = text_buf.toOwnedSlice();
410
411 const stream = &file.outStream().stream;
412 try stream.print("{}:{}:{}: error: {}\n", .{ path, start_loc.line + 1, start_loc.column + 1, text });
413
414 if (!color_on) return;
415
416 // Print \r and \t as one space each so that column counts line up
417 for (tree.source[start_loc.line_start..start_loc.line_end]) |byte| {
418 try stream.writeByte(switch (byte) {
419 '\r', '\t' => ' ',
420 else => byte,
421 });
422 }
423 try stream.writeByte('\n');
424 try stream.writeByteNTimes(' ', start_loc.column);
425 try stream.writeByteNTimes('~', last_token.end - first_token.start);
426 try stream.writeByte('\n');
427}
428
429export fn stage2_DepTokenizer_init(input: [*]const u8, len: usize) stage2_DepTokenizer {
430 const t = std.heap.c_allocator.create(DepTokenizer) catch @panic("failed to create .d tokenizer");
431 t.* = DepTokenizer.init(std.heap.c_allocator, input[0..len]);
432 return stage2_DepTokenizer{
433 .handle = t,
434 };
435}
436
437export fn stage2_DepTokenizer_deinit(self: *stage2_DepTokenizer) void {
438 self.handle.deinit();
439}
440
441export fn stage2_DepTokenizer_next(self: *stage2_DepTokenizer) stage2_DepNextResult {
442 const otoken = self.handle.next() catch {
443 const textz = std.Buffer.init(&self.handle.arena.allocator, self.handle.error_text) catch @panic("failed to create .d tokenizer error text");
444 return stage2_DepNextResult{
445 .type_id = .error_,
446 .textz = textz.toSlice().ptr,
447 };
448 };
449 const token = otoken orelse {
450 return stage2_DepNextResult{
451 .type_id = .null_,
452 .textz = undefined,
453 };
454 };
455 const textz = std.Buffer.init(&self.handle.arena.allocator, token.bytes) catch @panic("failed to create .d tokenizer token text");
456 return stage2_DepNextResult{
457 .type_id = switch (token.id) {
458 .target => .target,
459 .prereq => .prereq,
460 },
461 .textz = textz.toSlice().ptr,
462 };
463}
464
465const stage2_DepTokenizer = extern struct {
466 handle: *DepTokenizer,
467};
468
469const stage2_DepNextResult = extern struct {
470 type_id: TypeId,
471
472 // when type_id == error --> error text
473 // when type_id == null --> undefined
474 // when type_id == target --> target pathname
475 // when type_id == prereq --> prereq pathname
476 textz: [*]const u8,
477
478 const TypeId = extern enum {
479 error_,
480 null_,
481 target,
482 prereq,
483 };
484};
485
486// ABI warning
487export fn stage2_attach_segfault_handler() void {
488 if (std.debug.runtime_safety and std.debug.have_segfault_handling_support) {
489 std.debug.attachSegfaultHandler();
490 }
491}
492
493// ABI warning
494export fn stage2_progress_create() *std.Progress {
495 const ptr = std.heap.c_allocator.create(std.Progress) catch @panic("out of memory");
496 ptr.* = std.Progress{};
497 return ptr;
498}
499
500// ABI warning
501export fn stage2_progress_destroy(progress: *std.Progress) void {
502 std.heap.c_allocator.destroy(progress);
503}
504
505// ABI warning
506export fn stage2_progress_start_root(
507 progress: *std.Progress,
508 name_ptr: [*]const u8,
509 name_len: usize,
510 estimated_total_items: usize,
511) *std.Progress.Node {
512 return progress.start(
513 name_ptr[0..name_len],
514 if (estimated_total_items == 0) null else estimated_total_items,
515 ) catch @panic("timer unsupported");
516}
517
518// ABI warning
519export fn stage2_progress_disable_tty(progress: *std.Progress) void {
520 progress.terminal = null;
521}
522
523// ABI warning
524export fn stage2_progress_start(
525 node: *std.Progress.Node,
526 name_ptr: [*]const u8,
527 name_len: usize,
528 estimated_total_items: usize,
529) *std.Progress.Node {
530 const child_node = std.heap.c_allocator.create(std.Progress.Node) catch @panic("out of memory");
531 child_node.* = node.start(
532 name_ptr[0..name_len],
533 if (estimated_total_items == 0) null else estimated_total_items,
534 );
535 child_node.activate();
536 return child_node;
537}
538
539// ABI warning
540export fn stage2_progress_end(node: *std.Progress.Node) void {
541 node.end();
542 if (&node.context.root != node) {
543 std.heap.c_allocator.destroy(node);
544 }
545}
546
547// ABI warning
548export fn stage2_progress_complete_one(node: *std.Progress.Node) void {
549 node.completeOne();
550}
551
552// ABI warning
553export fn stage2_progress_update_node(node: *std.Progress.Node, done_count: usize, total_count: usize) void {
554 node.completed_items = done_count;
555 node.estimated_total_items = total_count;
556 node.activate();
557 node.context.maybeRefresh();
558}
559
560fn cpuFeaturesFromLLVM(
561 arch: Target.Arch,
562 llvm_cpu_name_z: ?[*:0]const u8,
563 llvm_cpu_features_opt: ?[*:0]const u8,
564) !Target.CpuFeatures {
565 var result = arch.getBaselineCpuFeatures();
566
567 if (llvm_cpu_name_z) |cpu_name_z| {
568 const llvm_cpu_name = mem.toSliceConst(u8, cpu_name_z);
569
570 for (arch.allCpus()) |cpu| {
571 const this_llvm_name = cpu.llvm_name orelse continue;
572 if (mem.eql(u8, this_llvm_name, llvm_cpu_name)) {
573 // Here we use the non-dependencies-populated set,
574 // so that subtracting features later in this function
575 // affect the prepopulated set.
576 result = Target.CpuFeatures{
577 .cpu = cpu,
578 .features = cpu.features,
579 };
580 break;
581 }
582 }
583 }
584
585 const all_features = arch.allFeaturesList();
586
587 if (llvm_cpu_features_opt) |llvm_cpu_features| {
588 var it = mem.tokenize(mem.toSliceConst(u8, llvm_cpu_features), ",");
589 while (it.next()) |decorated_llvm_feat| {
590 var op: enum {
591 add,
592 sub,
593 } = undefined;
594 var llvm_feat: []const u8 = undefined;
595 if (mem.startsWith(u8, decorated_llvm_feat, "+")) {
596 op = .add;
597 llvm_feat = decorated_llvm_feat[1..];
598 } else if (mem.startsWith(u8, decorated_llvm_feat, "-")) {
599 op = .sub;
600 llvm_feat = decorated_llvm_feat[1..];
601 } else {
602 return error.InvalidLlvmCpuFeaturesFormat;
603 }
604 for (all_features) |feature, index_usize| {
605 const this_llvm_name = feature.llvm_name orelse continue;
606 if (mem.eql(u8, llvm_feat, this_llvm_name)) {
607 const index = @intCast(Target.Cpu.Feature.Set.Index, index_usize);
608 switch (op) {
609 .add => result.features.addFeature(index),
610 .sub => result.features.removeFeature(index),
611 }
612 break;
613 }
614 }
615 }
616 }
617
618 result.features.populateDependencies(all_features);
619 return result;
620}
621
622// ABI warning
623export fn stage2_cmd_targets(zig_triple: [*:0]const u8) c_int {
624 cmdTargets(zig_triple) catch |err| {
625 std.debug.warn("unable to list targets: {}\n", .{@errorName(err)});
626 return -1;
627 };
628 return 0;
629}
630
631fn cmdTargets(zig_triple: [*:0]const u8) !void {
632 var target = try Target.parse(mem.toSliceConst(u8, zig_triple));
633 target.Cross.cpu_features = blk: {
634 const llvm = @import("llvm.zig");
635 const llvm_cpu_name = llvm.GetHostCPUName();
636 const llvm_cpu_features = llvm.GetNativeFeatures();
637 break :blk try cpuFeaturesFromLLVM(target.Cross.arch, llvm_cpu_name, llvm_cpu_features);
638 };
639 return @import("print_targets.zig").cmdTargets(
640 std.heap.c_allocator,
641 &[0][]u8{},
642 &std.io.getStdOut().outStream().stream,
643 target,
644 );
645}
646
647const Stage2CpuFeatures = struct {
648 allocator: *mem.Allocator,
649 cpu_features: Target.CpuFeatures,
650
651 llvm_features_str: ?[*:0]const u8,
652
653 builtin_str: [:0]const u8,
654 cache_hash: [:0]const u8,
655
656 const Self = @This();
657
658 fn createFromNative(allocator: *mem.Allocator) !*Self {
659 const arch = Target.current.getArch();
660 const llvm = @import("llvm.zig");
661 const llvm_cpu_name = llvm.GetHostCPUName();
662 const llvm_cpu_features = llvm.GetNativeFeatures();
663 const cpu_features = try cpuFeaturesFromLLVM(arch, llvm_cpu_name, llvm_cpu_features);
664 return createFromCpuFeatures(allocator, arch, cpu_features);
665 }
666
667 fn createFromCpuFeatures(
668 allocator: *mem.Allocator,
669 arch: Target.Arch,
670 cpu_features: Target.CpuFeatures,
671 ) !*Self {
672 const self = try allocator.create(Self);
673 errdefer allocator.destroy(self);
674
675 const cache_hash = try std.fmt.allocPrint0(allocator, "{}\n{}", .{
676 cpu_features.cpu.name,
677 cpu_features.features.asBytes(),
678 });
679 errdefer allocator.free(cache_hash);
680
681 const generic_arch_name = arch.genericName();
682 var builtin_str_buffer = try std.Buffer.allocPrint(allocator,
683 \\CpuFeatures{{
684 \\ .cpu = &Target.{}.cpu.{},
685 \\ .features = Target.{}.featureSet(&[_]Target.{}.Feature{{
686 \\
687 , .{
688 generic_arch_name,
689 cpu_features.cpu.name,
690 generic_arch_name,
691 generic_arch_name,
692 });
693 defer builtin_str_buffer.deinit();
694
695 var llvm_features_buffer = try std.Buffer.initSize(allocator, 0);
696 defer llvm_features_buffer.deinit();
697
698 for (arch.allFeaturesList()) |feature, index_usize| {
699 const index = @intCast(Target.Cpu.Feature.Set.Index, index_usize);
700 const is_enabled = cpu_features.features.isEnabled(index);
701
702 if (feature.llvm_name) |llvm_name| {
703 const plus_or_minus = "-+"[@boolToInt(is_enabled)];
704 try llvm_features_buffer.appendByte(plus_or_minus);
705 try llvm_features_buffer.append(llvm_name);
706 try llvm_features_buffer.append(",");
707 }
708
709 if (is_enabled) {
710 // TODO some kind of "zig identifier escape" function rather than
711 // unconditionally using @"" syntax
712 try builtin_str_buffer.append(" .@\"");
713 try builtin_str_buffer.append(feature.name);
714 try builtin_str_buffer.append("\",\n");
715 }
716 }
717
718 try builtin_str_buffer.append(
719 \\ }),
720 \\};
721 \\
722 );
723
724 assert(mem.endsWith(u8, llvm_features_buffer.toSliceConst(), ","));
725 llvm_features_buffer.shrink(llvm_features_buffer.len() - 1);
726
727 self.* = Self{
728 .allocator = allocator,
729 .cpu_features = cpu_features,
730 .llvm_features_str = llvm_features_buffer.toOwnedSlice().ptr,
731 .builtin_str = builtin_str_buffer.toOwnedSlice(),
732 .cache_hash = cache_hash,
733 };
734 return self;
735 }
736
737 fn destroy(self: *Self) void {
738 self.allocator.free(self.cache_hash);
739 self.allocator.free(self.builtin_str);
740 // TODO if (self.llvm_features_str) |llvm_features_str| self.allocator.free(llvm_features_str);
741 self.allocator.destroy(self);
742 }
743};
744
745// ABI warning
746export fn stage2_cpu_features_parse(
747 result: **Stage2CpuFeatures,
748 zig_triple: ?[*:0]const u8,
749 cpu_name: ?[*:0]const u8,
750 cpu_features: ?[*:0]const u8,
751) Error {
752 result.* = stage2ParseCpuFeatures(zig_triple, cpu_name, cpu_features) catch |err| switch (err) {
753 error.OutOfMemory => return .OutOfMemory,
754 error.UnknownArchitecture => return .UnknownArchitecture,
755 error.UnknownSubArchitecture => return .UnknownSubArchitecture,
756 error.UnknownOperatingSystem => return .UnknownOperatingSystem,
757 error.UnknownApplicationBinaryInterface => return .UnknownApplicationBinaryInterface,
758 error.MissingOperatingSystem => return .MissingOperatingSystem,
759 error.MissingArchitecture => return .MissingArchitecture,
760 error.InvalidLlvmCpuFeaturesFormat => return .InvalidLlvmCpuFeaturesFormat,
761 error.InvalidCpuFeatures => return .InvalidCpuFeatures,
762 };
763 return .None;
764}
765
766fn stage2ParseCpuFeatures(
767 zig_triple_oz: ?[*:0]const u8,
768 cpu_name_oz: ?[*:0]const u8,
769 cpu_features_oz: ?[*:0]const u8,
770) !*Stage2CpuFeatures {
771 const zig_triple_z = zig_triple_oz orelse return Stage2CpuFeatures.createFromNative(std.heap.c_allocator);
772 const target = try Target.parse(mem.toSliceConst(u8, zig_triple_z));
773 const arch = target.Cross.arch;
774
775 const cpu = if (cpu_name_oz) |cpu_name_z| blk: {
776 const cpu_name = mem.toSliceConst(u8, cpu_name_z);
777 break :blk arch.parseCpu(cpu_name) catch |err| switch (err) {
778 error.UnknownCpu => {
779 std.debug.warn("Unknown CPU: '{}'\nAvailable CPUs for architecture '{}':\n", .{
780 cpu_name,
781 @tagName(arch),
782 });
783 for (arch.allCpus()) |cpu| {
784 std.debug.warn(" {}\n", .{cpu.name});
785 }
786 process.exit(1);
787 },
788 else => |e| return e,
789 };
790 } else target.Cross.cpu_features.cpu;
791
792 var set = if (cpu_features_oz) |cpu_features_z| blk: {
793 const cpu_features = mem.toSliceConst(u8, cpu_features_z);
794 break :blk arch.parseCpuFeatureSet(cpu, cpu_features) catch |err| switch (err) {
795 error.UnknownCpuFeature => {
796 std.debug.warn(
797 \\Unknown CPU features specified.
798 \\Available CPU features for architecture '{}':
799 \\
800 , .{@tagName(arch)});
801 for (arch.allFeaturesList()) |feature| {
802 std.debug.warn(" {}\n", .{feature.name});
803 }
804 process.exit(1);
805 },
806 else => |e| return e,
807 };
808 } else cpu.features;
809
810 if (arch.subArchFeature()) |index| {
811 set.addFeature(index);
812 }
813 set.populateDependencies(arch.allFeaturesList());
814
815 return Stage2CpuFeatures.createFromCpuFeatures(std.heap.c_allocator, arch, .{
816 .cpu = cpu,
817 .features = set,
818 });
819}
820
821// ABI warning
822export fn stage2_cpu_features_get_cache_hash(
823 cpu_features: *const Stage2CpuFeatures,
824 ptr: *[*:0]const u8,
825 len: *usize,
826) void {
827 ptr.* = cpu_features.cache_hash.ptr;
828 len.* = cpu_features.cache_hash.len;
829}
830
831// ABI warning
832export fn stage2_cpu_features_get_builtin_str(
833 cpu_features: *const Stage2CpuFeatures,
834 ptr: *[*:0]const u8,
835 len: *usize,
836) void {
837 ptr.* = cpu_features.builtin_str.ptr;
838 len.* = cpu_features.builtin_str.len;
839}
840
841// ABI warning
842export fn stage2_cpu_features_get_llvm_cpu(cpu_features: *const Stage2CpuFeatures) ?[*:0]const u8 {
843 return if (cpu_features.cpu_features.cpu.llvm_name) |s| s.ptr else null;
844}
845
846// ABI warning
847export fn stage2_cpu_features_get_llvm_features(cpu_features: *const Stage2CpuFeatures) ?[*:0]const u8 {
848 return cpu_features.llvm_features_str;
849}
850
851// ABI warning
852const Stage2LibCInstallation = extern struct {
853 include_dir: [*:0]const u8,
854 include_dir_len: usize,
855 sys_include_dir: [*:0]const u8,
856 sys_include_dir_len: usize,
857 crt_dir: [*:0]const u8,
858 crt_dir_len: usize,
859 static_crt_dir: [*:0]const u8,
860 static_crt_dir_len: usize,
861 msvc_lib_dir: [*:0]const u8,
862 msvc_lib_dir_len: usize,
863 kernel32_lib_dir: [*:0]const u8,
864 kernel32_lib_dir_len: usize,
865
866 fn initFromStage2(self: *Stage2LibCInstallation, libc: LibCInstallation) void {
867 if (libc.include_dir) |s| {
868 self.include_dir = s.ptr;
869 self.include_dir_len = s.len;
870 } else {
871 self.include_dir = "";
872 self.include_dir_len = 0;
873 }
874 if (libc.sys_include_dir) |s| {
875 self.sys_include_dir = s.ptr;
876 self.sys_include_dir_len = s.len;
877 } else {
878 self.sys_include_dir = "";
879 self.sys_include_dir_len = 0;
880 }
881 if (libc.crt_dir) |s| {
882 self.crt_dir = s.ptr;
883 self.crt_dir_len = s.len;
884 } else {
885 self.crt_dir = "";
886 self.crt_dir_len = 0;
887 }
888 if (libc.static_crt_dir) |s| {
889 self.static_crt_dir = s.ptr;
890 self.static_crt_dir_len = s.len;
891 } else {
892 self.static_crt_dir = "";
893 self.static_crt_dir_len = 0;
894 }
895 if (libc.msvc_lib_dir) |s| {
896 self.msvc_lib_dir = s.ptr;
897 self.msvc_lib_dir_len = s.len;
898 } else {
899 self.msvc_lib_dir = "";
900 self.msvc_lib_dir_len = 0;
901 }
902 if (libc.kernel32_lib_dir) |s| {
903 self.kernel32_lib_dir = s.ptr;
904 self.kernel32_lib_dir_len = s.len;
905 } else {
906 self.kernel32_lib_dir = "";
907 self.kernel32_lib_dir_len = 0;
908 }
909 }
910
911 fn toStage2(self: Stage2LibCInstallation) LibCInstallation {
912 var libc: LibCInstallation = .{};
913 if (self.include_dir_len != 0) {
914 libc.include_dir = self.include_dir[0..self.include_dir_len :0];
915 }
916 if (self.sys_include_dir_len != 0) {
917 libc.sys_include_dir = self.sys_include_dir[0..self.sys_include_dir_len :0];
918 }
919 if (self.crt_dir_len != 0) {
920 libc.crt_dir = self.crt_dir[0..self.crt_dir_len :0];
921 }
922 if (self.static_crt_dir_len != 0) {
923 libc.static_crt_dir = self.static_crt_dir[0..self.static_crt_dir_len :0];
924 }
925 if (self.msvc_lib_dir_len != 0) {
926 libc.msvc_lib_dir = self.msvc_lib_dir[0..self.msvc_lib_dir_len :0];
927 }
928 if (self.kernel32_lib_dir_len != 0) {
929 libc.kernel32_lib_dir = self.kernel32_lib_dir[0..self.kernel32_lib_dir_len :0];
930 }
931 return libc;
932 }
933};
934
935// ABI warning
936export fn stage2_libc_parse(stage1_libc: *Stage2LibCInstallation, libc_file_z: [*:0]const u8) Error {
937 stderr_file = std.io.getStdErr();
938 stderr = &stderr_file.outStream().stream;
939 const libc_file = mem.toSliceConst(u8, libc_file_z);
940 var libc = LibCInstallation.parse(std.heap.c_allocator, libc_file, stderr) catch |err| switch (err) {
941 error.ParseError => return .SemanticAnalyzeFail,
942 error.DiskQuota => return .DiskQuota,
943 error.FileTooBig => return .FileTooBig,
944 error.InputOutput => return .FileSystem,
945 error.NoSpaceLeft => return .NoSpaceLeft,
946 error.AccessDenied => return .AccessDenied,
947 error.BrokenPipe => return .BrokenPipe,
948 error.SystemResources => return .SystemResources,
949 error.OperationAborted => return .OperationAborted,
950 error.WouldBlock => unreachable,
951 error.Unexpected => return .Unexpected,
952 error.EndOfStream => return .EndOfFile,
953 error.IsDir => return .IsDir,
954 error.ConnectionResetByPeer => unreachable,
955 error.OutOfMemory => return .OutOfMemory,
956 error.Unseekable => unreachable,
957 error.SharingViolation => return .SharingViolation,
958 error.PathAlreadyExists => unreachable,
959 error.FileNotFound => return .FileNotFound,
960 error.PipeBusy => return .PipeBusy,
961 error.NameTooLong => return .PathTooLong,
962 error.InvalidUtf8 => return .BadPathName,
963 error.BadPathName => return .BadPathName,
964 error.SymLinkLoop => return .SymLinkLoop,
965 error.ProcessFdQuotaExceeded => return .ProcessFdQuotaExceeded,
966 error.SystemFdQuotaExceeded => return .SystemFdQuotaExceeded,
967 error.NoDevice => return .NoDevice,
968 error.NotDir => return .NotDir,
969 error.DeviceBusy => return .DeviceBusy,
970 };
971 stage1_libc.initFromStage2(libc);
972 return .None;
973}
974
975// ABI warning
976export fn stage2_libc_find_native(stage1_libc: *Stage2LibCInstallation) Error {
977 var libc = LibCInstallation.findNative(std.heap.c_allocator) catch |err| switch (err) {
978 error.OutOfMemory => return .OutOfMemory,
979 error.FileSystem => return .FileSystem,
980 error.UnableToSpawnCCompiler => return .UnableToSpawnCCompiler,
981 error.CCompilerExitCode => return .CCompilerExitCode,
982 error.CCompilerCrashed => return .CCompilerCrashed,
983 error.CCompilerCannotFindHeaders => return .CCompilerCannotFindHeaders,
984 error.LibCRuntimeNotFound => return .LibCRuntimeNotFound,
985 error.LibCStdLibHeaderNotFound => return .LibCStdLibHeaderNotFound,
986 error.LibCKernel32LibNotFound => return .LibCKernel32LibNotFound,
987 error.UnsupportedArchitecture => return .UnsupportedArchitecture,
988 };
989 stage1_libc.initFromStage2(libc);
990 return .None;
991}
992
993// ABI warning
994export fn stage2_libc_render(stage1_libc: *Stage2LibCInstallation, output_file: *FILE) Error {
995 var libc = stage1_libc.toStage2();
996 const c_out_stream = &std.io.COutStream.init(output_file).stream;
997 libc.render(c_out_stream) catch |err| switch (err) {
998 error.WouldBlock => unreachable, // stage1 opens stuff in exclusively blocking mode
999 error.SystemResources => return .SystemResources,
1000 error.OperationAborted => return .OperationAborted,
1001 error.BrokenPipe => return .BrokenPipe,
1002 error.DiskQuota => return .DiskQuota,
1003 error.FileTooBig => return .FileTooBig,
1004 error.NoSpaceLeft => return .NoSpaceLeft,
1005 error.AccessDenied => return .AccessDenied,
1006 error.Unexpected => return .Unexpected,
1007 error.InputOutput => return .FileSystem,
1008 };
1009 return .None;
1010}
1011
1012// ABI warning
1013export fn stage2_libc_cc_print_file_name(
1014 out_ptr: *[*:0]u8,
1015 out_len: *usize,
1016 o_file: [*:0]const u8,
1017 want_dirname: bool,
1018) Error {
1019 const result = @import("libc_installation.zig").ccPrintFileName(
1020 std.heap.c_allocator,
1021 mem.toSliceConst(u8, o_file),
1022 if (want_dirname) .only_dir else .full_path,
1023 ) catch |err| switch (err) {
1024 error.OutOfMemory => return .OutOfMemory,
1025 error.LibCRuntimeNotFound => return .FileNotFound,
1026 error.CCompilerExitCode => return .CCompilerExitCode,
1027 error.CCompilerCrashed => return .CCompilerCrashed,
1028 error.UnableToSpawnCCompiler => return .UnableToSpawnCCompiler,
1029 };
1030 out_ptr.* = result.ptr;
1031 out_len.* = result.len;
1032 return .None;
1033}
src/cache_hash.cpp+1-1
......@@ -5,7 +5,7 @@
55 * See http://opensource.org/licenses/MIT
66 */
77
8#include "userland.h"
8#include "stage2.h"
99#include "cache_hash.hpp"
1010#include "all_types.hpp"
1111#include "buffer.hpp"
src/codegen.cpp+1-1
......@@ -18,7 +18,7 @@
1818#include "target.hpp"
1919#include "util.hpp"
2020#include "zig_llvm.h"
21#include "userland.h"
21#include "stage2.h"
2222#include "dump_analysis.hpp"
2323#include "softfloat.hpp"
2424#include "mem_profile.hpp"
src/codegen.hpp+1-1
......@@ -11,7 +11,7 @@
1111#include "parser.hpp"
1212#include "errmsg.hpp"
1313#include "target.hpp"
14#include "userland.h"
14#include "stage2.h"
1515
1616#include <stdio.h>
1717
src/error.hpp+1-1
......@@ -8,7 +8,7 @@
88#ifndef ERROR_HPP
99#define ERROR_HPP
1010
11#include "userland.h"
11#include "stage2.h"
1212
1313const char *err_str(Error err);
1414
src/main.cpp+1-1
......@@ -14,7 +14,7 @@
1414#include "heap.hpp"
1515#include "os.hpp"
1616#include "target.hpp"
17#include "userland.h"
17#include "stage2.h"
1818#include "glibc.hpp"
1919#include "dump_analysis.hpp"
2020#include "mem_profile.hpp"
src/stage2.cpp created+179
......@@ -0,0 +1,179 @@
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 <stdio.h>
8#include <stdlib.h>
9#include <string.h>
10
11Error stage2_translate_c(struct Stage2Ast **out_ast,
12 struct Stage2ErrorMsg **out_errors_ptr, size_t *out_errors_len,
13 const char **args_begin, const char **args_end, const char *resources_path)
14{
15 const char *msg = "stage0 called stage2_translate_c";
16 stage2_panic(msg, strlen(msg));
17}
18
19void stage2_free_clang_errors(struct Stage2ErrorMsg *ptr, size_t len) {
20 const char *msg = "stage0 called stage2_free_clang_errors";
21 stage2_panic(msg, strlen(msg));
22}
23
24void stage2_zen(const char **ptr, size_t *len) {
25 const char *msg = "stage0 called stage2_zen";
26 stage2_panic(msg, strlen(msg));
27}
28
29void stage2_attach_segfault_handler(void) { }
30
31void stage2_panic(const char *ptr, size_t len) {
32 fwrite(ptr, 1, len, stderr);
33 fprintf(stderr, "\n");
34 fflush(stderr);
35 abort();
36}
37
38void stage2_render_ast(struct Stage2Ast *ast, FILE *output_file) {
39 const char *msg = "stage0 called stage2_render_ast";
40 stage2_panic(msg, strlen(msg));
41}
42
43int stage2_fmt(int argc, char **argv) {
44 const char *msg = "stage0 called stage2_fmt";
45 stage2_panic(msg, strlen(msg));
46}
47
48stage2_DepTokenizer stage2_DepTokenizer_init(const char *input, size_t len) {
49 const char *msg = "stage0 called stage2_DepTokenizer_init";
50 stage2_panic(msg, strlen(msg));
51}
52
53void stage2_DepTokenizer_deinit(stage2_DepTokenizer *self) {
54 const char *msg = "stage0 called stage2_DepTokenizer_deinit";
55 stage2_panic(msg, strlen(msg));
56}
57
58stage2_DepNextResult stage2_DepTokenizer_next(stage2_DepTokenizer *self) {
59 const char *msg = "stage0 called stage2_DepTokenizer_next";
60 stage2_panic(msg, strlen(msg));
61}
62
63
64struct Stage2Progress {
65 int trash;
66};
67
68struct Stage2ProgressNode {
69 int trash;
70};
71
72Stage2Progress *stage2_progress_create(void) {
73 return nullptr;
74}
75
76void stage2_progress_destroy(Stage2Progress *progress) {}
77
78Stage2ProgressNode *stage2_progress_start_root(Stage2Progress *progress,
79 const char *name_ptr, size_t name_len, size_t estimated_total_items)
80{
81 return nullptr;
82}
83Stage2ProgressNode *stage2_progress_start(Stage2ProgressNode *node,
84 const char *name_ptr, size_t name_len, size_t estimated_total_items)
85{
86 return nullptr;
87}
88void stage2_progress_end(Stage2ProgressNode *node) {}
89void stage2_progress_complete_one(Stage2ProgressNode *node) {}
90void stage2_progress_disable_tty(Stage2Progress *progress) {}
91void stage2_progress_update_node(Stage2ProgressNode *node, size_t completed_count, size_t estimated_total_items){}
92
93struct Stage2CpuFeatures {
94 const char *llvm_cpu_name;
95 const char *llvm_cpu_features;
96 const char *builtin_str;
97 const char *cache_hash;
98};
99
100Error stage2_cpu_features_parse(struct Stage2CpuFeatures **out, const char *zig_triple,
101 const char *cpu_name, const char *cpu_features)
102{
103 if (zig_triple == nullptr) {
104 Stage2CpuFeatures *result = heap::c_allocator.create<Stage2CpuFeatures>();
105 result->llvm_cpu_name = ZigLLVMGetHostCPUName();
106 result->llvm_cpu_features = ZigLLVMGetNativeFeatures();
107 result->builtin_str = "arch.getBaselineCpuFeatures();\n";
108 result->cache_hash = "native\n\n";
109 *out = result;
110 return ErrorNone;
111 }
112 if (cpu_name == nullptr && cpu_features == nullptr) {
113 Stage2CpuFeatures *result = heap::c_allocator.create<Stage2CpuFeatures>();
114 result->builtin_str = "arch.getBaselineCpuFeatures();\n";
115 result->cache_hash = "\n\n";
116 *out = result;
117 return ErrorNone;
118 }
119
120 const char *msg = "stage0 called stage2_cpu_features_parse with non-null cpu name or features";
121 stage2_panic(msg, strlen(msg));
122}
123
124void stage2_cpu_features_get_cache_hash(const Stage2CpuFeatures *cpu_features,
125 const char **ptr, size_t *len)
126{
127 *ptr = cpu_features->cache_hash;
128 *len = strlen(cpu_features->cache_hash);
129}
130const char *stage2_cpu_features_get_llvm_cpu(const Stage2CpuFeatures *cpu_features) {
131 return cpu_features->llvm_cpu_name;
132}
133const char *stage2_cpu_features_get_llvm_features(const Stage2CpuFeatures *cpu_features) {
134 return cpu_features->llvm_cpu_features;
135}
136void stage2_cpu_features_get_builtin_str(const Stage2CpuFeatures *cpu_features,
137 const char **ptr, size_t *len)
138{
139 *ptr = cpu_features->builtin_str;
140 *len = strlen(cpu_features->builtin_str);
141}
142
143int stage2_cmd_targets(const char *zig_triple) {
144 const char *msg = "stage0 called stage2_cmd_targets";
145 stage2_panic(msg, strlen(msg));
146}
147
148enum Error stage2_libc_parse(struct Stage2LibCInstallation *libc, const char *libc_file) {
149 libc->include_dir = "/dummy/include";
150 libc->include_dir_len = strlen(libc->include_dir);
151 libc->sys_include_dir = "/dummy/sys/include";
152 libc->sys_include_dir_len = strlen(libc->sys_include_dir);
153 libc->crt_dir = "";
154 libc->crt_dir_len = strlen(libc->crt_dir);
155 libc->static_crt_dir = "";
156 libc->static_crt_dir_len = strlen(libc->static_crt_dir);
157 libc->msvc_lib_dir = "";
158 libc->msvc_lib_dir_len = strlen(libc->msvc_lib_dir);
159 libc->kernel32_lib_dir = "";
160 libc->kernel32_lib_dir_len = strlen(libc->kernel32_lib_dir);
161 return ErrorNone;
162}
163
164enum Error stage2_libc_render(struct Stage2LibCInstallation *self, FILE *file) {
165 const char *msg = "stage0 called stage2_libc_render";
166 stage2_panic(msg, strlen(msg));
167}
168
169enum Error stage2_libc_find_native(struct Stage2LibCInstallation *libc) {
170 const char *msg = "stage0 called stage2_libc_find_native";
171 stage2_panic(msg, strlen(msg));
172}
173
174enum Error stage2_libc_cc_print_file_name(char **out_ptr, size_t *out_len,
175 const char *o_file, bool want_dirname)
176{
177 const char *msg = "stage0 called stage2_libc_cc_print_file_name";
178 stage2_panic(msg, strlen(msg));
179}
src/stage2.h created+248
......@@ -0,0 +1,248 @@
1/*
2 * Copyright (c) 2019 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#ifndef ZIG_STAGE2_H
9#define ZIG_STAGE2_H
10
11#include <stddef.h>
12#include <stdint.h>
13#include <stdio.h>
14
15#ifdef __cplusplus
16#define ZIG_EXTERN_C extern "C"
17#else
18#define ZIG_EXTERN_C
19#endif
20
21#if defined(_MSC_VER)
22#define ZIG_ATTRIBUTE_NORETURN __declspec(noreturn)
23#else
24#define ZIG_ATTRIBUTE_NORETURN __attribute__((noreturn))
25#endif
26
27// ABI warning: the types and declarations in this file must match both those in
28// stage2.cpp and src-self-hosted/stage2.zig.
29
30// ABI warning
31enum Error {
32 ErrorNone,
33 ErrorNoMem,
34 ErrorInvalidFormat,
35 ErrorSemanticAnalyzeFail,
36 ErrorAccess,
37 ErrorInterrupted,
38 ErrorSystemResources,
39 ErrorFileNotFound,
40 ErrorFileSystem,
41 ErrorFileTooBig,
42 ErrorDivByZero,
43 ErrorOverflow,
44 ErrorPathAlreadyExists,
45 ErrorUnexpected,
46 ErrorExactDivRemainder,
47 ErrorNegativeDenominator,
48 ErrorShiftedOutOneBits,
49 ErrorCCompileErrors,
50 ErrorEndOfFile,
51 ErrorIsDir,
52 ErrorNotDir,
53 ErrorUnsupportedOperatingSystem,
54 ErrorSharingViolation,
55 ErrorPipeBusy,
56 ErrorPrimitiveTypeNotFound,
57 ErrorCacheUnavailable,
58 ErrorPathTooLong,
59 ErrorCCompilerCannotFindFile,
60 ErrorNoCCompilerInstalled,
61 ErrorReadingDepFile,
62 ErrorInvalidDepFile,
63 ErrorMissingArchitecture,
64 ErrorMissingOperatingSystem,
65 ErrorUnknownArchitecture,
66 ErrorUnknownOperatingSystem,
67 ErrorUnknownABI,
68 ErrorInvalidFilename,
69 ErrorDiskQuota,
70 ErrorDiskSpace,
71 ErrorUnexpectedWriteFailure,
72 ErrorUnexpectedSeekFailure,
73 ErrorUnexpectedFileTruncationFailure,
74 ErrorUnimplemented,
75 ErrorOperationAborted,
76 ErrorBrokenPipe,
77 ErrorNoSpaceLeft,
78 ErrorNotLazy,
79 ErrorIsAsync,
80 ErrorImportOutsidePkgPath,
81 ErrorUnknownCpu,
82 ErrorUnknownSubArchitecture,
83 ErrorUnknownCpuFeature,
84 ErrorInvalidCpuFeatures,
85 ErrorInvalidLlvmCpuFeaturesFormat,
86 ErrorUnknownApplicationBinaryInterface,
87 ErrorASTUnitFailure,
88 ErrorBadPathName,
89 ErrorSymLinkLoop,
90 ErrorProcessFdQuotaExceeded,
91 ErrorSystemFdQuotaExceeded,
92 ErrorNoDevice,
93 ErrorDeviceBusy,
94 ErrorUnableToSpawnCCompiler,
95 ErrorCCompilerExitCode,
96 ErrorCCompilerCrashed,
97 ErrorCCompilerCannotFindHeaders,
98 ErrorLibCRuntimeNotFound,
99 ErrorLibCStdLibHeaderNotFound,
100 ErrorLibCKernel32LibNotFound,
101 ErrorUnsupportedArchitecture,
102};
103
104// ABI warning
105struct Stage2ErrorMsg {
106 const char *filename_ptr; // can be null
107 size_t filename_len;
108 const char *msg_ptr;
109 size_t msg_len;
110 const char *source; // valid until the ASTUnit is freed. can be null
111 unsigned line; // 0 based
112 unsigned column; // 0 based
113 unsigned offset; // byte offset into source
114};
115
116// ABI warning
117struct Stage2Ast;
118
119// ABI warning
120ZIG_EXTERN_C enum Error stage2_translate_c(struct Stage2Ast **out_ast,
121 struct Stage2ErrorMsg **out_errors_ptr, size_t *out_errors_len,
122 const char **args_begin, const char **args_end, const char *resources_path);
123
124// ABI warning
125ZIG_EXTERN_C void stage2_free_clang_errors(struct Stage2ErrorMsg *ptr, size_t len);
126
127// ABI warning
128ZIG_EXTERN_C void stage2_render_ast(struct Stage2Ast *ast, FILE *output_file);
129
130// ABI warning
131ZIG_EXTERN_C void stage2_zen(const char **ptr, size_t *len);
132
133// ABI warning
134ZIG_EXTERN_C void stage2_attach_segfault_handler(void);
135
136// ABI warning
137ZIG_EXTERN_C ZIG_ATTRIBUTE_NORETURN void stage2_panic(const char *ptr, size_t len);
138
139// ABI warning
140ZIG_EXTERN_C int stage2_fmt(int argc, char **argv);
141
142// ABI warning
143struct stage2_DepTokenizer {
144 void *handle;
145};
146
147// ABI warning
148struct stage2_DepNextResult {
149 enum TypeId {
150 error,
151 null,
152 target,
153 prereq,
154 };
155
156 TypeId type_id;
157
158 // when ent == error --> error text
159 // when ent == null --> undefined
160 // when ent == target --> target pathname
161 // when ent == prereq --> prereq pathname
162 const char *textz;
163};
164
165// ABI warning
166ZIG_EXTERN_C stage2_DepTokenizer stage2_DepTokenizer_init(const char *input, size_t len);
167
168// ABI warning
169ZIG_EXTERN_C void stage2_DepTokenizer_deinit(stage2_DepTokenizer *self);
170
171// ABI warning
172ZIG_EXTERN_C stage2_DepNextResult stage2_DepTokenizer_next(stage2_DepTokenizer *self);
173
174// ABI warning
175struct Stage2Progress;
176// ABI warning
177struct Stage2ProgressNode;
178// ABI warning
179ZIG_EXTERN_C Stage2Progress *stage2_progress_create(void);
180// ABI warning
181ZIG_EXTERN_C void stage2_progress_disable_tty(Stage2Progress *progress);
182// ABI warning
183ZIG_EXTERN_C void stage2_progress_destroy(Stage2Progress *progress);
184// ABI warning
185ZIG_EXTERN_C Stage2ProgressNode *stage2_progress_start_root(Stage2Progress *progress,
186 const char *name_ptr, size_t name_len, size_t estimated_total_items);
187// ABI warning
188ZIG_EXTERN_C Stage2ProgressNode *stage2_progress_start(Stage2ProgressNode *node,
189 const char *name_ptr, size_t name_len, size_t estimated_total_items);
190// ABI warning
191ZIG_EXTERN_C void stage2_progress_end(Stage2ProgressNode *node);
192// ABI warning
193ZIG_EXTERN_C void stage2_progress_complete_one(Stage2ProgressNode *node);
194// ABI warning
195ZIG_EXTERN_C void stage2_progress_update_node(Stage2ProgressNode *node,
196 size_t completed_count, size_t estimated_total_items);
197
198// ABI warning
199struct Stage2CpuFeatures;
200
201// ABI warning
202ZIG_EXTERN_C enum Error stage2_cpu_features_parse(struct Stage2CpuFeatures **result,
203 const char *zig_triple, const char *cpu_name, const char *cpu_features);
204
205// ABI warning
206ZIG_EXTERN_C const char *stage2_cpu_features_get_llvm_cpu(const struct Stage2CpuFeatures *cpu_features);
207
208// ABI warning
209ZIG_EXTERN_C const char *stage2_cpu_features_get_llvm_features(const struct Stage2CpuFeatures *cpu_features);
210
211// ABI warning
212ZIG_EXTERN_C void stage2_cpu_features_get_builtin_str(const struct Stage2CpuFeatures *cpu_features,
213 const char **ptr, size_t *len);
214
215// ABI warning
216ZIG_EXTERN_C void stage2_cpu_features_get_cache_hash(const struct Stage2CpuFeatures *cpu_features,
217 const char **ptr, size_t *len);
218
219// ABI warning
220ZIG_EXTERN_C int stage2_cmd_targets(const char *zig_triple);
221
222// ABI warning
223struct Stage2LibCInstallation {
224 const char *include_dir;
225 size_t include_dir_len;
226 const char *sys_include_dir;
227 size_t sys_include_dir_len;
228 const char *crt_dir;
229 size_t crt_dir_len;
230 const char *static_crt_dir;
231 size_t static_crt_dir_len;
232 const char *msvc_lib_dir;
233 size_t msvc_lib_dir_len;
234 const char *kernel32_lib_dir;
235 size_t kernel32_lib_dir_len;
236};
237
238// ABI warning
239ZIG_EXTERN_C enum Error stage2_libc_parse(struct Stage2LibCInstallation *libc, const char *libc_file);
240// ABI warning
241ZIG_EXTERN_C enum Error stage2_libc_render(struct Stage2LibCInstallation *self, FILE *file);
242// ABI warning
243ZIG_EXTERN_C enum Error stage2_libc_find_native(struct Stage2LibCInstallation *libc);
244// ABI warning
245ZIG_EXTERN_C enum Error stage2_libc_cc_print_file_name(char **out_ptr, size_t *out_len,
246 const char *o_file, bool want_dirname);
247
248#endif
src/userland.cpp deleted-179
......@@ -1,179 +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 "userland.h"
5#include "util.hpp"
6#include "zig_llvm.h"
7#include <stdio.h>
8#include <stdlib.h>
9#include <string.h>
10
11Error stage2_translate_c(struct Stage2Ast **out_ast,
12 struct Stage2ErrorMsg **out_errors_ptr, size_t *out_errors_len,
13 const char **args_begin, const char **args_end, const char *resources_path)
14{
15 const char *msg = "stage0 called stage2_translate_c";
16 stage2_panic(msg, strlen(msg));
17}
18
19void stage2_free_clang_errors(struct Stage2ErrorMsg *ptr, size_t len) {
20 const char *msg = "stage0 called stage2_free_clang_errors";
21 stage2_panic(msg, strlen(msg));
22}
23
24void stage2_zen(const char **ptr, size_t *len) {
25 const char *msg = "stage0 called stage2_zen";
26 stage2_panic(msg, strlen(msg));
27}
28
29void stage2_attach_segfault_handler(void) { }
30
31void stage2_panic(const char *ptr, size_t len) {
32 fwrite(ptr, 1, len, stderr);
33 fprintf(stderr, "\n");
34 fflush(stderr);
35 abort();
36}
37
38void stage2_render_ast(struct Stage2Ast *ast, FILE *output_file) {
39 const char *msg = "stage0 called stage2_render_ast";
40 stage2_panic(msg, strlen(msg));
41}
42
43int stage2_fmt(int argc, char **argv) {
44 const char *msg = "stage0 called stage2_fmt";
45 stage2_panic(msg, strlen(msg));
46}
47
48stage2_DepTokenizer stage2_DepTokenizer_init(const char *input, size_t len) {
49 const char *msg = "stage0 called stage2_DepTokenizer_init";
50 stage2_panic(msg, strlen(msg));
51}
52
53void stage2_DepTokenizer_deinit(stage2_DepTokenizer *self) {
54 const char *msg = "stage0 called stage2_DepTokenizer_deinit";
55 stage2_panic(msg, strlen(msg));
56}
57
58stage2_DepNextResult stage2_DepTokenizer_next(stage2_DepTokenizer *self) {
59 const char *msg = "stage0 called stage2_DepTokenizer_next";
60 stage2_panic(msg, strlen(msg));
61}
62
63
64struct Stage2Progress {
65 int trash;
66};
67
68struct Stage2ProgressNode {
69 int trash;
70};
71
72Stage2Progress *stage2_progress_create(void) {
73 return nullptr;
74}
75
76void stage2_progress_destroy(Stage2Progress *progress) {}
77
78Stage2ProgressNode *stage2_progress_start_root(Stage2Progress *progress,
79 const char *name_ptr, size_t name_len, size_t estimated_total_items)
80{
81 return nullptr;
82}
83Stage2ProgressNode *stage2_progress_start(Stage2ProgressNode *node,
84 const char *name_ptr, size_t name_len, size_t estimated_total_items)
85{
86 return nullptr;
87}
88void stage2_progress_end(Stage2ProgressNode *node) {}
89void stage2_progress_complete_one(Stage2ProgressNode *node) {}
90void stage2_progress_disable_tty(Stage2Progress *progress) {}
91void stage2_progress_update_node(Stage2ProgressNode *node, size_t completed_count, size_t estimated_total_items){}
92
93struct Stage2CpuFeatures {
94 const char *llvm_cpu_name;
95 const char *llvm_cpu_features;
96 const char *builtin_str;
97 const char *cache_hash;
98};
99
100Error stage2_cpu_features_parse(struct Stage2CpuFeatures **out, const char *zig_triple,
101 const char *cpu_name, const char *cpu_features)
102{
103 if (zig_triple == nullptr) {
104 Stage2CpuFeatures *result = heap::c_allocator.create<Stage2CpuFeatures>();
105 result->llvm_cpu_name = ZigLLVMGetHostCPUName();
106 result->llvm_cpu_features = ZigLLVMGetNativeFeatures();
107 result->builtin_str = "arch.getBaselineCpuFeatures();\n";
108 result->cache_hash = "native\n\n";
109 *out = result;
110 return ErrorNone;
111 }
112 if (cpu_name == nullptr && cpu_features == nullptr) {
113 Stage2CpuFeatures *result = heap::c_allocator.create<Stage2CpuFeatures>();
114 result->builtin_str = "arch.getBaselineCpuFeatures();\n";
115 result->cache_hash = "\n\n";
116 *out = result;
117 return ErrorNone;
118 }
119
120 const char *msg = "stage0 called stage2_cpu_features_parse with non-null cpu name or features";
121 stage2_panic(msg, strlen(msg));
122}
123
124void stage2_cpu_features_get_cache_hash(const Stage2CpuFeatures *cpu_features,
125 const char **ptr, size_t *len)
126{
127 *ptr = cpu_features->cache_hash;
128 *len = strlen(cpu_features->cache_hash);
129}
130const char *stage2_cpu_features_get_llvm_cpu(const Stage2CpuFeatures *cpu_features) {
131 return cpu_features->llvm_cpu_name;
132}
133const char *stage2_cpu_features_get_llvm_features(const Stage2CpuFeatures *cpu_features) {
134 return cpu_features->llvm_cpu_features;
135}
136void stage2_cpu_features_get_builtin_str(const Stage2CpuFeatures *cpu_features,
137 const char **ptr, size_t *len)
138{
139 *ptr = cpu_features->builtin_str;
140 *len = strlen(cpu_features->builtin_str);
141}
142
143int stage2_cmd_targets(const char *zig_triple) {
144 const char *msg = "stage0 called stage2_cmd_targets";
145 stage2_panic(msg, strlen(msg));
146}
147
148enum Error stage2_libc_parse(struct Stage2LibCInstallation *libc, const char *libc_file) {
149 libc->include_dir = "/dummy/include";
150 libc->include_dir_len = strlen(libc->include_dir);
151 libc->sys_include_dir = "/dummy/sys/include";
152 libc->sys_include_dir_len = strlen(libc->sys_include_dir);
153 libc->crt_dir = "";
154 libc->crt_dir_len = strlen(libc->crt_dir);
155 libc->static_crt_dir = "";
156 libc->static_crt_dir_len = strlen(libc->static_crt_dir);
157 libc->msvc_lib_dir = "";
158 libc->msvc_lib_dir_len = strlen(libc->msvc_lib_dir);
159 libc->kernel32_lib_dir = "";
160 libc->kernel32_lib_dir_len = strlen(libc->kernel32_lib_dir);
161 return ErrorNone;
162}
163
164enum Error stage2_libc_render(struct Stage2LibCInstallation *self, FILE *file) {
165 const char *msg = "stage0 called stage2_libc_render";
166 stage2_panic(msg, strlen(msg));
167}
168
169enum Error stage2_libc_find_native(struct Stage2LibCInstallation *libc) {
170 const char *msg = "stage0 called stage2_libc_find_native";
171 stage2_panic(msg, strlen(msg));
172}
173
174enum Error stage2_libc_cc_print_file_name(char **out_ptr, size_t *out_len,
175 const char *o_file, bool want_dirname)
176{
177 const char *msg = "stage0 called stage2_libc_cc_print_file_name";
178 stage2_panic(msg, strlen(msg));
179}
src/userland.h deleted-248
......@@ -1,248 +0,0 @@
1/*
2 * Copyright (c) 2019 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#ifndef ZIG_USERLAND_H
9#define ZIG_USERLAND_H
10
11#include <stddef.h>
12#include <stdint.h>
13#include <stdio.h>
14
15#ifdef __cplusplus
16#define ZIG_EXTERN_C extern "C"
17#else
18#define ZIG_EXTERN_C
19#endif
20
21#if defined(_MSC_VER)
22#define ZIG_ATTRIBUTE_NORETURN __declspec(noreturn)
23#else
24#define ZIG_ATTRIBUTE_NORETURN __attribute__((noreturn))
25#endif
26
27// ABI warning: the types and declarations in this file must match both those in
28// userland.cpp and src-self-hosted/stage1.zig.
29
30// ABI warning
31enum Error {
32 ErrorNone,
33 ErrorNoMem,
34 ErrorInvalidFormat,
35 ErrorSemanticAnalyzeFail,
36 ErrorAccess,
37 ErrorInterrupted,
38 ErrorSystemResources,
39 ErrorFileNotFound,
40 ErrorFileSystem,
41 ErrorFileTooBig,
42 ErrorDivByZero,
43 ErrorOverflow,
44 ErrorPathAlreadyExists,
45 ErrorUnexpected,
46 ErrorExactDivRemainder,
47 ErrorNegativeDenominator,
48 ErrorShiftedOutOneBits,
49 ErrorCCompileErrors,
50 ErrorEndOfFile,
51 ErrorIsDir,
52 ErrorNotDir,
53 ErrorUnsupportedOperatingSystem,
54 ErrorSharingViolation,
55 ErrorPipeBusy,
56 ErrorPrimitiveTypeNotFound,
57 ErrorCacheUnavailable,
58 ErrorPathTooLong,
59 ErrorCCompilerCannotFindFile,
60 ErrorNoCCompilerInstalled,
61 ErrorReadingDepFile,
62 ErrorInvalidDepFile,
63 ErrorMissingArchitecture,
64 ErrorMissingOperatingSystem,
65 ErrorUnknownArchitecture,
66 ErrorUnknownOperatingSystem,
67 ErrorUnknownABI,
68 ErrorInvalidFilename,
69 ErrorDiskQuota,
70 ErrorDiskSpace,
71 ErrorUnexpectedWriteFailure,
72 ErrorUnexpectedSeekFailure,
73 ErrorUnexpectedFileTruncationFailure,
74 ErrorUnimplemented,
75 ErrorOperationAborted,
76 ErrorBrokenPipe,
77 ErrorNoSpaceLeft,
78 ErrorNotLazy,
79 ErrorIsAsync,
80 ErrorImportOutsidePkgPath,
81 ErrorUnknownCpu,
82 ErrorUnknownSubArchitecture,
83 ErrorUnknownCpuFeature,
84 ErrorInvalidCpuFeatures,
85 ErrorInvalidLlvmCpuFeaturesFormat,
86 ErrorUnknownApplicationBinaryInterface,
87 ErrorASTUnitFailure,
88 ErrorBadPathName,
89 ErrorSymLinkLoop,
90 ErrorProcessFdQuotaExceeded,
91 ErrorSystemFdQuotaExceeded,
92 ErrorNoDevice,
93 ErrorDeviceBusy,
94 ErrorUnableToSpawnCCompiler,
95 ErrorCCompilerExitCode,
96 ErrorCCompilerCrashed,
97 ErrorCCompilerCannotFindHeaders,
98 ErrorLibCRuntimeNotFound,
99 ErrorLibCStdLibHeaderNotFound,
100 ErrorLibCKernel32LibNotFound,
101 ErrorUnsupportedArchitecture,
102};
103
104// ABI warning
105struct Stage2ErrorMsg {
106 const char *filename_ptr; // can be null
107 size_t filename_len;
108 const char *msg_ptr;
109 size_t msg_len;
110 const char *source; // valid until the ASTUnit is freed. can be null
111 unsigned line; // 0 based
112 unsigned column; // 0 based
113 unsigned offset; // byte offset into source
114};
115
116// ABI warning
117struct Stage2Ast;
118
119// ABI warning
120ZIG_EXTERN_C enum Error stage2_translate_c(struct Stage2Ast **out_ast,
121 struct Stage2ErrorMsg **out_errors_ptr, size_t *out_errors_len,
122 const char **args_begin, const char **args_end, const char *resources_path);
123
124// ABI warning
125ZIG_EXTERN_C void stage2_free_clang_errors(struct Stage2ErrorMsg *ptr, size_t len);
126
127// ABI warning
128ZIG_EXTERN_C void stage2_render_ast(struct Stage2Ast *ast, FILE *output_file);
129
130// ABI warning
131ZIG_EXTERN_C void stage2_zen(const char **ptr, size_t *len);
132
133// ABI warning
134ZIG_EXTERN_C void stage2_attach_segfault_handler(void);
135
136// ABI warning
137ZIG_EXTERN_C ZIG_ATTRIBUTE_NORETURN void stage2_panic(const char *ptr, size_t len);
138
139// ABI warning
140ZIG_EXTERN_C int stage2_fmt(int argc, char **argv);
141
142// ABI warning
143struct stage2_DepTokenizer {
144 void *handle;
145};
146
147// ABI warning
148struct stage2_DepNextResult {
149 enum TypeId {
150 error,
151 null,
152 target,
153 prereq,
154 };
155
156 TypeId type_id;
157
158 // when ent == error --> error text
159 // when ent == null --> undefined
160 // when ent == target --> target pathname
161 // when ent == prereq --> prereq pathname
162 const char *textz;
163};
164
165// ABI warning
166ZIG_EXTERN_C stage2_DepTokenizer stage2_DepTokenizer_init(const char *input, size_t len);
167
168// ABI warning
169ZIG_EXTERN_C void stage2_DepTokenizer_deinit(stage2_DepTokenizer *self);
170
171// ABI warning
172ZIG_EXTERN_C stage2_DepNextResult stage2_DepTokenizer_next(stage2_DepTokenizer *self);
173
174// ABI warning
175struct Stage2Progress;
176// ABI warning
177struct Stage2ProgressNode;
178// ABI warning
179ZIG_EXTERN_C Stage2Progress *stage2_progress_create(void);
180// ABI warning
181ZIG_EXTERN_C void stage2_progress_disable_tty(Stage2Progress *progress);
182// ABI warning
183ZIG_EXTERN_C void stage2_progress_destroy(Stage2Progress *progress);
184// ABI warning
185ZIG_EXTERN_C Stage2ProgressNode *stage2_progress_start_root(Stage2Progress *progress,
186 const char *name_ptr, size_t name_len, size_t estimated_total_items);
187// ABI warning
188ZIG_EXTERN_C Stage2ProgressNode *stage2_progress_start(Stage2ProgressNode *node,
189 const char *name_ptr, size_t name_len, size_t estimated_total_items);
190// ABI warning
191ZIG_EXTERN_C void stage2_progress_end(Stage2ProgressNode *node);
192// ABI warning
193ZIG_EXTERN_C void stage2_progress_complete_one(Stage2ProgressNode *node);
194// ABI warning
195ZIG_EXTERN_C void stage2_progress_update_node(Stage2ProgressNode *node,
196 size_t completed_count, size_t estimated_total_items);
197
198// ABI warning
199struct Stage2CpuFeatures;
200
201// ABI warning
202ZIG_EXTERN_C enum Error stage2_cpu_features_parse(struct Stage2CpuFeatures **result,
203 const char *zig_triple, const char *cpu_name, const char *cpu_features);
204
205// ABI warning
206ZIG_EXTERN_C const char *stage2_cpu_features_get_llvm_cpu(const struct Stage2CpuFeatures *cpu_features);
207
208// ABI warning
209ZIG_EXTERN_C const char *stage2_cpu_features_get_llvm_features(const struct Stage2CpuFeatures *cpu_features);
210
211// ABI warning
212ZIG_EXTERN_C void stage2_cpu_features_get_builtin_str(const struct Stage2CpuFeatures *cpu_features,
213 const char **ptr, size_t *len);
214
215// ABI warning
216ZIG_EXTERN_C void stage2_cpu_features_get_cache_hash(const struct Stage2CpuFeatures *cpu_features,
217 const char **ptr, size_t *len);
218
219// ABI warning
220ZIG_EXTERN_C int stage2_cmd_targets(const char *zig_triple);
221
222// ABI warning
223struct Stage2LibCInstallation {
224 const char *include_dir;
225 size_t include_dir_len;
226 const char *sys_include_dir;
227 size_t sys_include_dir_len;
228 const char *crt_dir;
229 size_t crt_dir_len;
230 const char *static_crt_dir;
231 size_t static_crt_dir_len;
232 const char *msvc_lib_dir;
233 size_t msvc_lib_dir_len;
234 const char *kernel32_lib_dir;
235 size_t kernel32_lib_dir_len;
236};
237
238// ABI warning
239ZIG_EXTERN_C enum Error stage2_libc_parse(struct Stage2LibCInstallation *libc, const char *libc_file);
240// ABI warning
241ZIG_EXTERN_C enum Error stage2_libc_render(struct Stage2LibCInstallation *self, FILE *file);
242// ABI warning
243ZIG_EXTERN_C enum Error stage2_libc_find_native(struct Stage2LibCInstallation *libc);
244// ABI warning
245ZIG_EXTERN_C enum Error stage2_libc_cc_print_file_name(char **out_ptr, size_t *out_len,
246 const char *o_file, bool want_dirname);
247
248#endif
src/util.cpp+1-1
......@@ -6,7 +6,7 @@
66 */
77
88#include "util.hpp"
9#include "userland.h"
9#include "stage2.h"
1010
1111#include <stdio.h>
1212#include <stdarg.h>
src/zig_clang.h+1-1
......@@ -8,7 +8,7 @@
88#ifndef ZIG_ZIG_CLANG_H
99#define ZIG_ZIG_CLANG_H
1010
11#include "userland.h"
11#include "stage2.h"
1212#include <inttypes.h>
1313#include <stdbool.h>
1414