authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-12-23 00:29:39-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-12-23 00:57:56-05:00
log39c7bd24e4f768b23074b8634ac637b175b7639f
treee3454d346c9d37abb9bb56847d3743eeb6cfa4e8
parent760b307e8a8fcbb31fc1f2abb170ef7399aa917e

port most of main.cpp to self hosted compiler


10 files changed, 1156 insertions(+), 78 deletions(-)

README.md+29-24
...@@ -119,31 +119,22 @@ libc. Create demo games using Zig....@@ -119,31 +119,22 @@ libc. Create demo games using Zig.
119[![Build Status](https://travis-ci.org/zig-lang/zig.svg?branch=master)](https://travis-ci.org/zig-lang/zig)119[![Build Status](https://travis-ci.org/zig-lang/zig.svg?branch=master)](https://travis-ci.org/zig-lang/zig)
120[![Build status](https://ci.appveyor.com/api/projects/status/4t80mk2dmucrc38i/branch/master?svg=true)](https://ci.appveyor.com/project/andrewrk/zig-d3l86/branch/master)120[![Build status](https://ci.appveyor.com/api/projects/status/4t80mk2dmucrc38i/branch/master?svg=true)](https://ci.appveyor.com/project/andrewrk/zig-d3l86/branch/master)
121121
122### Dependencies122### Stage 1: Build Zig from C++ Source Code
123123
124#### Build Dependencies124#### Dependencies
125
126These compile tools must be available on your system and are used to build
127the Zig compiler itself:
128125
129##### POSIX126##### POSIX
130127
131 * gcc >= 5.0.0 or clang >= 3.6.0128 * gcc >= 5.0.0 or clang >= 3.6.0
132 * cmake >= 2.8.5129 * cmake >= 2.8.5
130 * LLVM, Clang, LLD libraries == 5.x, compiled with the same gcc or clang version above
133131
134##### Windows132##### Windows
135133
136 * Microsoft Visual Studio 2015134 * Microsoft Visual Studio 2015
135 * LLVM, Clang, LLD libraries == 5.x, compiled with the same MSVC version above
137136
138#### Library Dependencies137#### Instructions
139
140These libraries must be installed on your system, with the development files
141available. The Zig compiler links against them. You have to use the same
142compiler for these libraries as you do to compile Zig.
143
144 * LLVM, Clang, and LLD libraries == 5.x
145
146### Debug / Development Build
147138
148If you have gcc or clang installed, you can find out what `ZIG_LIBC_LIB_DIR`,139If you have gcc or clang installed, you can find out what `ZIG_LIBC_LIB_DIR`,
149`ZIG_LIBC_STATIC_LIB_DIR`, and `ZIG_LIBC_INCLUDE_DIR` should be set to140`ZIG_LIBC_STATIC_LIB_DIR`, and `ZIG_LIBC_INCLUDE_DIR` should be set to
...@@ -158,7 +149,7 @@ make install...@@ -158,7 +149,7 @@ make install
158./zig build --build-file ../build.zig test149./zig build --build-file ../build.zig test
159```150```
160151
161#### MacOS152##### MacOS
162153
163`ZIG_LIBC_LIB_DIR` and `ZIG_LIBC_STATIC_LIB_DIR` are unused.154`ZIG_LIBC_LIB_DIR` and `ZIG_LIBC_STATIC_LIB_DIR` are unused.
164155
...@@ -172,21 +163,35 @@ make install...@@ -172,21 +163,35 @@ make install
172./zig build --build-file ../build.zig test163./zig build --build-file ../build.zig test
173```164```
174165
175#### Windows166##### Windows
176167
177See https://github.com/zig-lang/zig/wiki/Building-Zig-on-Windows168See https://github.com/zig-lang/zig/wiki/Building-Zig-on-Windows
178169
179### Release / Install Build170### Stage 2: Build Self-Hosted Zig from Zig Source Code
180171
181Once installed, `ZIG_LIBC_LIB_DIR` and `ZIG_LIBC_INCLUDE_DIR` can be overridden172*Note: Stage 2 compiler is not complete. Beta users of Zig should use the
182by the `--libc-lib-dir` and `--libc-include-dir` parameters to the zig binary.173Stage 1 compiler for now.*
174
175Dependencies are the same as Stage 1, except now you have a working zig compiler.
183176
184```177```
185mkdir build178bin/zig build --build-file ../build.zig --prefix $(pwd)/stage2 install
186cd build179```
187cmake .. -DCMAKE_BUILD_TYPE=Release -DZIG_LIBC_LIB_DIR=/some/path -DZIG_LIBC_INCLUDE_DIR=/some/path -DZIG_LIBC_STATIC_INCLUDE_DIR=/some/path180
188make181### Stage 3: Rebuild Self-Hosted Zig Using the Self-Hosted Compiler
189sudo make install182
183This is the actual compiler binary that we will install to the system.
184
185#### Debug / Development Build
186
187```
188./stage2/bin/zig build --build-file ../build.zig --prefix $(pwd)/stage3 install
189```
190
191#### Release / Install Build
192
193```
194./stage2/bin/zig build --build-file ../build.zig install -Drelease-fast
190```195```
191196
192### Test Coverage197### Test Coverage
build.zig+136-9
...@@ -32,15 +32,18 @@ pub fn build(b: &Builder) {...@@ -32,15 +32,18 @@ pub fn build(b: &Builder) {
32 docs_step.dependOn(&docgen_cmd.step);32 docs_step.dependOn(&docgen_cmd.step);
33 docs_step.dependOn(&docgen_home_cmd.step);33 docs_step.dependOn(&docgen_home_cmd.step);
3434
35 var exe = b.addExecutable("zig", "src-self-hosted/main.zig");35 if (findLLVM(b)) |llvm| {
36 exe.setBuildMode(mode);36 var exe = b.addExecutable("zig", "src-self-hosted/main.zig");
37 exe.linkSystemLibrary("c");37 exe.setBuildMode(mode);
38 dependOnLib(exe, findLLVM(b));38 exe.linkSystemLibrary("c");
39 dependOnLib(exe, llvm);
3940
40 b.default_step.dependOn(&exe.step);41 b.default_step.dependOn(&exe.step);
41 b.default_step.dependOn(docs_step);42 b.default_step.dependOn(docs_step);
4243
43 b.installArtifact(exe);44 b.installArtifact(exe);
45 installStdLib(b);
46 }
4447
4548
46 const test_filter = b.option([]const u8, "test-filter", "Skip tests that do not match filter");49 const test_filter = b.option([]const u8, "test-filter", "Skip tests that do not match filter");
...@@ -91,7 +94,7 @@ const LibraryDep = struct {...@@ -91,7 +94,7 @@ const LibraryDep = struct {
91 includes: ArrayList([]const u8),94 includes: ArrayList([]const u8),
92};95};
9396
94fn findLLVM(b: &Builder) -> LibraryDep {97fn findLLVM(b: &Builder) -> ?LibraryDep {
95 const llvm_config_exe = b.findProgram(98 const llvm_config_exe = b.findProgram(
96 [][]const u8{"llvm-config-5.0", "llvm-config"},99 [][]const u8{"llvm-config-5.0", "llvm-config"},
97 [][]const u8{100 [][]const u8{
...@@ -102,7 +105,8 @@ fn findLLVM(b: &Builder) -> LibraryDep {...@@ -102,7 +105,8 @@ fn findLLVM(b: &Builder) -> LibraryDep {
102 "C:/Libraries/llvm-5.0.0/bin",105 "C:/Libraries/llvm-5.0.0/bin",
103 }) %% |err|106 }) %% |err|
104 {107 {
105 std.debug.panic("unable to find llvm-config: {}\n", err);108 warn("unable to find llvm-config: {}\n", err);
109 return null;
106 };110 };
107 const libs_output = b.exec([][]const u8{llvm_config_exe, "--libs", "--system-libs"});111 const libs_output = b.exec([][]const u8{llvm_config_exe, "--libs", "--system-libs"});
108 const includes_output = b.exec([][]const u8{llvm_config_exe, "--includedir"});112 const includes_output = b.exec([][]const u8{llvm_config_exe, "--includedir"});
...@@ -143,3 +147,126 @@ fn findLLVM(b: &Builder) -> LibraryDep {...@@ -143,3 +147,126 @@ fn findLLVM(b: &Builder) -> LibraryDep {
143 }147 }
144 return result;148 return result;
145}149}
150
151pub fn installStdLib(b: &Builder) {
152 const stdlib_files = []const []const u8 {
153 "array_list.zig",
154 "base64.zig",
155 "buf_map.zig",
156 "buf_set.zig",
157 "buffer.zig",
158 "build.zig",
159 "c/darwin.zig",
160 "c/index.zig",
161 "c/linux.zig",
162 "c/windows.zig",
163 "cstr.zig",
164 "debug.zig",
165 "dwarf.zig",
166 "elf.zig",
167 "empty.zig",
168 "endian.zig",
169 "fmt/errol/enum3.zig",
170 "fmt/errol/index.zig",
171 "fmt/errol/lookup.zig",
172 "fmt/index.zig",
173 "hash_map.zig",
174 "heap.zig",
175 "index.zig",
176 "io.zig",
177 "linked_list.zig",
178 "math/acos.zig",
179 "math/acosh.zig",
180 "math/asin.zig",
181 "math/asinh.zig",
182 "math/atan.zig",
183 "math/atan2.zig",
184 "math/atanh.zig",
185 "math/cbrt.zig",
186 "math/ceil.zig",
187 "math/copysign.zig",
188 "math/cos.zig",
189 "math/cosh.zig",
190 "math/exp.zig",
191 "math/exp2.zig",
192 "math/expm1.zig",
193 "math/expo2.zig",
194 "math/fabs.zig",
195 "math/floor.zig",
196 "math/fma.zig",
197 "math/frexp.zig",
198 "math/hypot.zig",
199 "math/ilogb.zig",
200 "math/index.zig",
201 "math/inf.zig",
202 "math/isfinite.zig",
203 "math/isinf.zig",
204 "math/isnan.zig",
205 "math/isnormal.zig",
206 "math/ln.zig",
207 "math/log.zig",
208 "math/log10.zig",
209 "math/log1p.zig",
210 "math/log2.zig",
211 "math/modf.zig",
212 "math/nan.zig",
213 "math/pow.zig",
214 "math/round.zig",
215 "math/scalbn.zig",
216 "math/signbit.zig",
217 "math/sin.zig",
218 "math/sinh.zig",
219 "math/sqrt.zig",
220 "math/tan.zig",
221 "math/tanh.zig",
222 "math/trunc.zig",
223 "mem.zig",
224 "net.zig",
225 "os/child_process.zig",
226 "os/darwin.zig",
227 "os/darwin_errno.zig",
228 "os/get_user_id.zig",
229 "os/index.zig",
230 "os/linux.zig",
231 "os/linux_errno.zig",
232 "os/linux_i386.zig",
233 "os/linux_x86_64.zig",
234 "os/path.zig",
235 "os/windows/error.zig",
236 "os/windows/index.zig",
237 "os/windows/util.zig",
238 "rand.zig",
239 "sort.zig",
240 "special/bootstrap.zig",
241 "special/bootstrap_lib.zig",
242 "special/build_file_template.zig",
243 "special/build_runner.zig",
244 "special/builtin.zig",
245 "special/compiler_rt/aulldiv.zig",
246 "special/compiler_rt/aullrem.zig",
247 "special/compiler_rt/comparetf2.zig",
248 "special/compiler_rt/fixuint.zig",
249 "special/compiler_rt/fixunsdfdi.zig",
250 "special/compiler_rt/fixunsdfsi.zig",
251 "special/compiler_rt/fixunsdfti.zig",
252 "special/compiler_rt/fixunssfdi.zig",
253 "special/compiler_rt/fixunssfsi.zig",
254 "special/compiler_rt/fixunssfti.zig",
255 "special/compiler_rt/fixunstfdi.zig",
256 "special/compiler_rt/fixunstfsi.zig",
257 "special/compiler_rt/fixunstfti.zig",
258 "special/compiler_rt/index.zig",
259 "special/compiler_rt/udivmod.zig",
260 "special/compiler_rt/udivmoddi4.zig",
261 "special/compiler_rt/udivmodti4.zig",
262 "special/compiler_rt/udivti3.zig",
263 "special/compiler_rt/umodti3.zig",
264 "special/panic.zig",
265 "special/test_runner.zig",
266 };
267 for (stdlib_files) |stdlib_file| {
268 const src_path = %%os.path.join(b.allocator, "std", stdlib_file);
269 const dest_path = %%os.path.join(b.allocator, "lib", "zig", "std", stdlib_file);
270 b.installFile(src_path, dest_path);
271 }
272}
src-self-hosted/llvm.zig created+13
...@@ -0,0 +1,13 @@
1const builtin = @import("builtin");
2const c = @import("c.zig");
3const assert = @import("std").debug.assert;
4
5pub const ValueRef = removeNullability(c.LLVMValueRef);
6pub const ModuleRef = removeNullability(c.LLVMModuleRef);
7pub const ContextRef = removeNullability(c.LLVMContextRef);
8pub const BuilderRef = removeNullability(c.LLVMBuilderRef);
9
10fn removeNullability(comptime T: type) -> type {
11 comptime assert(@typeId(T) == builtin.TypeId.Nullable);
12 return T.Child;
13}
src-self-hosted/main.zig+586-37
...@@ -4,71 +4,620 @@ const io = std.io;...@@ -4,71 +4,620 @@ const io = std.io;
4const os = std.os;4const os = std.os;
5const heap = std.heap;5const heap = std.heap;
6const warn = std.debug.warn;6const warn = std.debug.warn;
7const Tokenizer = @import("tokenizer.zig").Tokenizer;
8const Token = @import("tokenizer.zig").Token;
9const Parser = @import("parser.zig").Parser;
10const assert = std.debug.assert;7const assert = std.debug.assert;
11const target = @import("target.zig");8const target = @import("target.zig");
9const Target = target.Target;
10const Module = @import("module.zig").Module;
11const ErrColor = Module.ErrColor;
12const Emit = Module.Emit;
13const builtin = @import("builtin");
14const ArrayList = std.ArrayList;
15
16error InvalidCommandLineArguments;
17error ZigLibDirNotFound;
18error ZigInstallationNotFound;
19
20const default_zig_cache_name = "zig-cache";
1221
13pub fn main() -> %void {22pub fn main() -> %void {
14 main2() %% |err| {23 main2() %% |err| {
15 warn("{}\n", @errorName(err));24 if (err != error.InvalidCommandLineArguments) {
25 warn("{}\n", @errorName(err));
26 }
16 return err;27 return err;
17 };28 };
18}29}
1930
20pub fn main2() -> %void {31const Cmd = enum {
21 var incrementing_allocator = %return heap.IncrementingAllocator.init(10 * 1024 * 1024);32 None,
22 defer incrementing_allocator.deinit();33 Build,
34 Test,
35 Version,
36 Zen,
37 TranslateC,
38 Targets,
39};
2340
24 const allocator = &incrementing_allocator.allocator;41fn badArgs(comptime format: []const u8, args: ...) -> error {
42 var stderr = %return io.getStdErr();
43 var stderr_stream_adapter = io.FileOutStream.init(&stderr);
44 const stderr_stream = &stderr_stream_adapter.stream;
45 %return stderr_stream.print(format ++ "\n\n", args);
46 %return printUsage(&stderr_stream_adapter.stream);
47 return error.InvalidCommandLineArguments;
48}
49
50pub fn main2() -> %void {
51 const allocator = std.heap.c_allocator;
2552
26 const args = %return os.argsAlloc(allocator);53 const args = %return os.argsAlloc(allocator);
27 defer os.argsFree(allocator, args);54 defer os.argsFree(allocator, args);
2855
29 target.initializeAll();56 var cmd = Cmd.None;
57 var build_kind: Module.Kind = undefined;
58 var build_mode: builtin.Mode = builtin.Mode.Debug;
59 var color = ErrColor.Auto;
60 var emit_file_type = Emit.Binary;
61
62 var strip = false;
63 var is_static = false;
64 var verbose_tokenize = false;
65 var verbose_ast_tree = false;
66 var verbose_ast_fmt = false;
67 var verbose_link = false;
68 var verbose_ir = false;
69 var verbose_llvm_ir = false;
70 var verbose_cimport = false;
71 var mwindows = false;
72 var mconsole = false;
73 var rdynamic = false;
74 var each_lib_rpath = false;
75 var timing_info = false;
76
77 var in_file_arg: ?[]u8 = null;
78 var out_file: ?[]u8 = null;
79 var out_file_h: ?[]u8 = null;
80 var out_name_arg: ?[]u8 = null;
81 var libc_lib_dir_arg: ?[]u8 = null;
82 var libc_static_lib_dir_arg: ?[]u8 = null;
83 var libc_include_dir_arg: ?[]u8 = null;
84 var msvc_lib_dir_arg: ?[]u8 = null;
85 var kernel32_lib_dir_arg: ?[]u8 = null;
86 var zig_install_prefix: ?[]u8 = null;
87 var dynamic_linker_arg: ?[]u8 = null;
88 var cache_dir_arg: ?[]const u8 = null;
89 var target_arch: ?[]u8 = null;
90 var target_os: ?[]u8 = null;
91 var target_environ: ?[]u8 = null;
92 var mmacosx_version_min: ?[]u8 = null;
93 var mios_version_min: ?[]u8 = null;
94 var linker_script_arg: ?[]u8 = null;
95 var test_name_prefix_arg: ?[]u8 = null;
96
97 var test_filters = ArrayList([]const u8).init(allocator);
98 defer test_filters.deinit();
99
100 var lib_dirs = ArrayList([]const u8).init(allocator);
101 defer lib_dirs.deinit();
102
103 var clang_argv = ArrayList([]const u8).init(allocator);
104 defer clang_argv.deinit();
105
106 var llvm_argv = ArrayList([]const u8).init(allocator);
107 defer llvm_argv.deinit();
108
109 var link_libs = ArrayList([]const u8).init(allocator);
110 defer link_libs.deinit();
111
112 var frameworks = ArrayList([]const u8).init(allocator);
113 defer frameworks.deinit();
114
115 var objects = ArrayList([]const u8).init(allocator);
116 defer objects.deinit();
30117
31 const target_file = args[1];118 var asm_files = ArrayList([]const u8).init(allocator);
119 defer asm_files.deinit();
32120
33 const target_file_buf = %return io.readFileAlloc(target_file, allocator);121 var rpath_list = ArrayList([]const u8).init(allocator);
34 defer allocator.free(target_file_buf);122 defer rpath_list.deinit();
35123
36 var stderr_file = %return std.io.getStdErr();124 var ver_major: u32 = 0;
37 var stderr_file_out_stream = std.io.FileOutStream.init(&stderr_file);125 var ver_minor: u32 = 0;
38 const out_stream = &stderr_file_out_stream.stream;126 var ver_patch: u32 = 0;
39127
40 warn("====input:====\n");128 var arg_i: usize = 1;
129 while (arg_i < args.len) : (arg_i += 1) {
130 const arg = args[arg_i];
41131
42 warn("{}", target_file_buf);132 if (arg.len != 0 and arg[0] == '-') {
133 if (mem.eql(u8, arg, "--release-fast")) {
134 build_mode = builtin.Mode.ReleaseFast;
135 } else if (mem.eql(u8, arg, "--release-safe")) {
136 build_mode = builtin.Mode.ReleaseSafe;
137 } else if (mem.eql(u8, arg, "--strip")) {
138 strip = true;
139 } else if (mem.eql(u8, arg, "--static")) {
140 is_static = true;
141 } else if (mem.eql(u8, arg, "--verbose-tokenize")) {
142 verbose_tokenize = true;
143 } else if (mem.eql(u8, arg, "--verbose-ast-tree")) {
144 verbose_ast_tree = true;
145 } else if (mem.eql(u8, arg, "--verbose-ast-fmt")) {
146 verbose_ast_fmt = true;
147 } else if (mem.eql(u8, arg, "--verbose-link")) {
148 verbose_link = true;
149 } else if (mem.eql(u8, arg, "--verbose-ir")) {
150 verbose_ir = true;
151 } else if (mem.eql(u8, arg, "--verbose-llvm-ir")) {
152 verbose_llvm_ir = true;
153 } else if (mem.eql(u8, arg, "--verbose-cimport")) {
154 verbose_cimport = true;
155 } else if (mem.eql(u8, arg, "-mwindows")) {
156 mwindows = true;
157 } else if (mem.eql(u8, arg, "-mconsole")) {
158 mconsole = true;
159 } else if (mem.eql(u8, arg, "-rdynamic")) {
160 rdynamic = true;
161 } else if (mem.eql(u8, arg, "--each-lib-rpath")) {
162 each_lib_rpath = true;
163 } else if (mem.eql(u8, arg, "--enable-timing-info")) {
164 timing_info = true;
165 } else if (mem.eql(u8, arg, "--test-cmd-bin")) {
166 @panic("TODO --test-cmd-bin");
167 } else if (arg[1] == 'L' and arg.len > 2) {
168 // alias for --library-path
169 %return lib_dirs.append(arg[1..]);
170 } else if (mem.eql(u8, arg, "--pkg-begin")) {
171 @panic("TODO --pkg-begin");
172 } else if (mem.eql(u8, arg, "--pkg-end")) {
173 @panic("TODO --pkg-end");
174 } else if (arg_i + 1 >= args.len) {
175 return badArgs("expected another argument after {}", arg);
176 } else {
177 arg_i += 1;
178 if (mem.eql(u8, arg, "--output")) {
179 out_file = args[arg_i];
180 } else if (mem.eql(u8, arg, "--output-h")) {
181 out_file_h = args[arg_i];
182 } else if (mem.eql(u8, arg, "--color")) {
183 if (mem.eql(u8, args[arg_i], "auto")) {
184 color = ErrColor.Auto;
185 } else if (mem.eql(u8, args[arg_i], "on")) {
186 color = ErrColor.On;
187 } else if (mem.eql(u8, args[arg_i], "off")) {
188 color = ErrColor.Off;
189 } else {
190 return badArgs("--color options are 'auto', 'on', or 'off'");
191 }
192 } else if (mem.eql(u8, arg, "--emit")) {
193 if (mem.eql(u8, args[arg_i], "asm")) {
194 emit_file_type = Emit.Assembly;
195 } else if (mem.eql(u8, args[arg_i], "bin")) {
196 emit_file_type = Emit.Binary;
197 } else if (mem.eql(u8, args[arg_i], "llvm-ir")) {
198 emit_file_type = Emit.LlvmIr;
199 } else {
200 return badArgs("--emit options are 'asm', 'bin', or 'llvm-ir'");
201 }
202 } else if (mem.eql(u8, arg, "--name")) {
203 out_name_arg = args[arg_i];
204 } else if (mem.eql(u8, arg, "--libc-lib-dir")) {
205 libc_lib_dir_arg = args[arg_i];
206 } else if (mem.eql(u8, arg, "--libc-static-lib-dir")) {
207 libc_static_lib_dir_arg = args[arg_i];
208 } else if (mem.eql(u8, arg, "--libc-include-dir")) {
209 libc_include_dir_arg = args[arg_i];
210 } else if (mem.eql(u8, arg, "--msvc-lib-dir")) {
211 msvc_lib_dir_arg = args[arg_i];
212 } else if (mem.eql(u8, arg, "--kernel32-lib-dir")) {
213 kernel32_lib_dir_arg = args[arg_i];
214 } else if (mem.eql(u8, arg, "--zig-install-prefix")) {
215 zig_install_prefix = args[arg_i];
216 } else if (mem.eql(u8, arg, "--dynamic-linker")) {
217 dynamic_linker_arg = args[arg_i];
218 } else if (mem.eql(u8, arg, "-isystem")) {
219 %return clang_argv.append("-isystem");
220 %return clang_argv.append(args[arg_i]);
221 } else if (mem.eql(u8, arg, "-dirafter")) {
222 %return clang_argv.append("-dirafter");
223 %return clang_argv.append(args[arg_i]);
224 } else if (mem.eql(u8, arg, "-mllvm")) {
225 %return clang_argv.append("-mllvm");
226 %return clang_argv.append(args[arg_i]);
43227
44 warn("====tokenization:====\n");228 %return llvm_argv.append(args[arg_i]);
45 {229 } else if (mem.eql(u8, arg, "--library-path") or mem.eql(u8, arg, "-L")) {
46 var tokenizer = Tokenizer.init(target_file_buf);230 %return lib_dirs.append(args[arg_i]);
47 while (true) {231 } else if (mem.eql(u8, arg, "--library")) {
48 const token = tokenizer.next();232 %return link_libs.append(args[arg_i]);
49 tokenizer.dump(token);233 } else if (mem.eql(u8, arg, "--object")) {
50 if (token.id == Token.Id.Eof) {234 %return objects.append(args[arg_i]);
51 break;235 } else if (mem.eql(u8, arg, "--assembly")) {
236 %return asm_files.append(args[arg_i]);
237 } else if (mem.eql(u8, arg, "--cache-dir")) {
238 cache_dir_arg = args[arg_i];
239 } else if (mem.eql(u8, arg, "--target-arch")) {
240 target_arch = args[arg_i];
241 } else if (mem.eql(u8, arg, "--target-os")) {
242 target_os = args[arg_i];
243 } else if (mem.eql(u8, arg, "--target-environ")) {
244 target_environ = args[arg_i];
245 } else if (mem.eql(u8, arg, "-mmacosx-version-min")) {
246 mmacosx_version_min = args[arg_i];
247 } else if (mem.eql(u8, arg, "-mios-version-min")) {
248 mios_version_min = args[arg_i];
249 } else if (mem.eql(u8, arg, "-framework")) {
250 %return frameworks.append(args[arg_i]);
251 } else if (mem.eql(u8, arg, "--linker-script")) {
252 linker_script_arg = args[arg_i];
253 } else if (mem.eql(u8, arg, "-rpath")) {
254 %return rpath_list.append(args[arg_i]);
255 } else if (mem.eql(u8, arg, "--test-filter")) {
256 %return test_filters.append(args[arg_i]);
257 } else if (mem.eql(u8, arg, "--test-name-prefix")) {
258 test_name_prefix_arg = args[arg_i];
259 } else if (mem.eql(u8, arg, "--ver-major")) {
260 ver_major = %return std.fmt.parseUnsigned(u32, args[arg_i], 10);
261 } else if (mem.eql(u8, arg, "--ver-minor")) {
262 ver_minor = %return std.fmt.parseUnsigned(u32, args[arg_i], 10);
263 } else if (mem.eql(u8, arg, "--ver-patch")) {
264 ver_patch = %return std.fmt.parseUnsigned(u32, args[arg_i], 10);
265 } else if (mem.eql(u8, arg, "--test-cmd")) {
266 @panic("TODO --test-cmd");
267 } else {
268 return badArgs("invalid argument: {}", arg);
269 }
52 }270 }
271 } else if (cmd == Cmd.None) {
272 if (mem.eql(u8, arg, "build-obj")) {
273 cmd = Cmd.Build;
274 build_kind = Module.Kind.Obj;
275 } else if (mem.eql(u8, arg, "build-exe")) {
276 cmd = Cmd.Build;
277 build_kind = Module.Kind.Exe;
278 } else if (mem.eql(u8, arg, "build-lib")) {
279 cmd = Cmd.Build;
280 build_kind = Module.Kind.Lib;
281 } else if (mem.eql(u8, arg, "version")) {
282 cmd = Cmd.Version;
283 } else if (mem.eql(u8, arg, "zen")) {
284 cmd = Cmd.Zen;
285 } else if (mem.eql(u8, arg, "translate-c")) {
286 cmd = Cmd.TranslateC;
287 } else if (mem.eql(u8, arg, "test")) {
288 cmd = Cmd.Test;
289 build_kind = Module.Kind.Exe;
290 } else {
291 return badArgs("unrecognized command: {}", arg);
292 }
293 } else switch (cmd) {
294 Cmd.Build, Cmd.TranslateC, Cmd.Test => {
295 if (in_file_arg == null) {
296 in_file_arg = arg;
297 } else {
298 return badArgs("unexpected extra parameter: {}", arg);
299 }
300 },
301 Cmd.Version, Cmd.Zen, Cmd.Targets => {
302 return badArgs("unexpected extra parameter: {}", arg);
303 },
304 Cmd.None => unreachable,
53 }305 }
54 }306 }
55307
56 warn("====parse:====\n");308 target.initializeAll();
309
310 // TODO
311// ZigTarget alloc_target;
312// ZigTarget *target;
313// if (!target_arch && !target_os && !target_environ) {
314// target = nullptr;
315// } else {
316// target = &alloc_target;
317// get_unknown_target(target);
318// if (target_arch) {
319// if (parse_target_arch(target_arch, &target->arch)) {
320// fprintf(stderr, "invalid --target-arch argument\n");
321// return usage(arg0);
322// }
323// }
324// if (target_os) {
325// if (parse_target_os(target_os, &target->os)) {
326// fprintf(stderr, "invalid --target-os argument\n");
327// return usage(arg0);
328// }
329// }
330// if (target_environ) {
331// if (parse_target_environ(target_environ, &target->env_type)) {
332// fprintf(stderr, "invalid --target-environ argument\n");
333// return usage(arg0);
334// }
335// }
336// }
337
338 switch (cmd) {
339 Cmd.None => return badArgs("expected command"),
340 Cmd.Zen => return printZen(),
341 Cmd.Build, Cmd.Test, Cmd.TranslateC => {
342 if (cmd == Cmd.Build and in_file_arg == null and objects.len == 0 and asm_files.len == 0) {
343 return badArgs("expected source file argument or at least one --object or --assembly argument");
344 } else if ((cmd == Cmd.TranslateC or cmd == Cmd.Test) and in_file_arg == null) {
345 return badArgs("expected source file argument");
346 } else if (cmd == Cmd.Build and build_kind == Module.Kind.Obj and objects.len != 0) {
347 return badArgs("When building an object file, --object arguments are invalid");
348 }
349
350 const root_name = switch (cmd) {
351 Cmd.Build, Cmd.TranslateC => x: {
352 if (out_name_arg) |out_name| {
353 break :x out_name;
354 } else if (in_file_arg) |in_file_path| {
355 const basename = os.path.basename(in_file_path);
356 var it = mem.split(basename, ".");
357 break :x it.next() ?? return badArgs("file name cannot be empty");
358 } else {
359 return badArgs("--name [name] not provided and unable to infer");
360 }
361 },
362 Cmd.Test => "test",
363 else => unreachable,
364 };
365
366 const zig_root_source_file = if (cmd == Cmd.TranslateC) null else in_file_arg;
367
368 const chosen_cache_dir = cache_dir_arg ?? default_zig_cache_name;
369 const full_cache_dir = %return os.path.resolve(allocator, ".", chosen_cache_dir);
370 defer allocator.free(full_cache_dir);
371
372 const zig_lib_dir = %return resolveZigLibDir(allocator, zig_install_prefix);
373 %defer allocator.free(zig_lib_dir);
374
375 const module = %return Module.create(allocator, root_name, zig_root_source_file,
376 Target.Native, build_kind, build_mode, zig_lib_dir, full_cache_dir);
377 defer module.destroy();
378
379 module.version_major = ver_major;
380 module.version_minor = ver_minor;
381 module.version_patch = ver_patch;
382
383 module.is_test = cmd == Cmd.Test;
384 if (linker_script_arg) |linker_script| {
385 module.linker_script = linker_script;
386 }
387 module.each_lib_rpath = each_lib_rpath;
388 module.clang_argv = clang_argv.toSliceConst();
389 module.llvm_argv = llvm_argv.toSliceConst();
390 module.strip = strip;
391 module.is_static = is_static;
392
393 if (libc_lib_dir_arg) |libc_lib_dir| {
394 module.libc_lib_dir = libc_lib_dir;
395 }
396 if (libc_static_lib_dir_arg) |libc_static_lib_dir| {
397 module.libc_static_lib_dir = libc_static_lib_dir;
398 }
399 if (libc_include_dir_arg) |libc_include_dir| {
400 module.libc_include_dir = libc_include_dir;
401 }
402 if (msvc_lib_dir_arg) |msvc_lib_dir| {
403 module.msvc_lib_dir = msvc_lib_dir;
404 }
405 if (kernel32_lib_dir_arg) |kernel32_lib_dir| {
406 module.kernel32_lib_dir = kernel32_lib_dir;
407 }
408 if (dynamic_linker_arg) |dynamic_linker| {
409 module.dynamic_linker = dynamic_linker;
410 }
411 module.verbose_tokenize = verbose_tokenize;
412 module.verbose_ast_tree = verbose_ast_tree;
413 module.verbose_ast_fmt = verbose_ast_fmt;
414 module.verbose_link = verbose_link;
415 module.verbose_ir = verbose_ir;
416 module.verbose_llvm_ir = verbose_llvm_ir;
417 module.verbose_cimport = verbose_cimport;
418
419 module.err_color = color;
420
421 module.lib_dirs = lib_dirs.toSliceConst();
422 module.darwin_frameworks = frameworks.toSliceConst();
423 module.rpath_list = rpath_list.toSliceConst();
424
425 for (link_libs.toSliceConst()) |name| {
426 _ = %return module.addLinkLib(name, true);
427 }
428
429 module.windows_subsystem_windows = mwindows;
430 module.windows_subsystem_console = mconsole;
431 module.linker_rdynamic = rdynamic;
432
433 if (mmacosx_version_min != null and mios_version_min != null) {
434 return badArgs("-mmacosx-version-min and -mios-version-min options not allowed together");
435 }
436
437 if (mmacosx_version_min) |ver| {
438 module.darwin_version_min = Module.DarwinVersionMin { .MacOS = ver };
439 } else if (mios_version_min) |ver| {
440 module.darwin_version_min = Module.DarwinVersionMin { .Ios = ver };
441 }
442
443 module.test_filters = test_filters.toSliceConst();
444 module.test_name_prefix = test_name_prefix_arg;
445 module.out_h_path = out_file_h;
446
447 // TODO
448 //add_package(g, cur_pkg, g->root_package);
449
450 switch (cmd) {
451 Cmd.Build => {
452 module.emit_file_type = emit_file_type;
453
454 module.link_objects = objects.toSliceConst();
455 module.assembly_files = asm_files.toSliceConst();
456
457 %return module.build();
458 %return module.link(out_file);
459 },
460 Cmd.TranslateC => @panic("TODO translate-c"),
461 Cmd.Test => @panic("TODO test cmd"),
462 else => unreachable,
463 }
464 },
465 Cmd.Version => @panic("TODO zig version"),
466 Cmd.Targets => @panic("TODO zig targets"),
467 }
468}
469
470fn printUsage(stream: &io.OutStream) -> %void {
471 %return stream.write(
472 \\Usage: zig [command] [options]
473 \\
474 \\Commands:
475 \\ build build project from build.zig
476 \\ build-exe [source] create executable from source or object files
477 \\ build-lib [source] create library from source or object files
478 \\ build-obj [source] create object from source or assembly
479 \\ translate-c [source] convert c code to zig code
480 \\ targets list available compilation targets
481 \\ test [source] create and run a test build
482 \\ version print version number and exit
483 \\ zen print zen of zig and exit
484 \\Compile Options:
485 \\ --assembly [source] add assembly file to build
486 \\ --cache-dir [path] override the cache directory
487 \\ --color [auto|off|on] enable or disable colored error messages
488 \\ --emit [filetype] emit a specific file format as compilation output
489 \\ --enable-timing-info print timing diagnostics
490 \\ --libc-include-dir [path] directory where libc stdlib.h resides
491 \\ --name [name] override output name
492 \\ --output [file] override destination path
493 \\ --output-h [file] override generated header file path
494 \\ --pkg-begin [name] [path] make package available to import and push current pkg
495 \\ --pkg-end pop current pkg
496 \\ --release-fast build with optimizations on and safety off
497 \\ --release-safe build with optimizations on and safety on
498 \\ --static output will be statically linked
499 \\ --strip exclude debug symbols
500 \\ --target-arch [name] specify target architecture
501 \\ --target-environ [name] specify target environment
502 \\ --target-os [name] specify target operating system
503 \\ --verbose-tokenize enable compiler debug info: tokenization
504 \\ --verbose-ast-tree enable compiler debug info: parsing into an AST (treeview)
505 \\ --verbose-ast-fmt enable compiler debug info: parsing into an AST (render source)
506 \\ --verbose-cimport enable compiler debug info: C imports
507 \\ --verbose-ir enable compiler debug info: Zig IR
508 \\ --verbose-llvm-ir enable compiler debug info: LLVM IR
509 \\ --verbose-link enable compiler debug info: linking
510 \\ --zig-install-prefix [path] override directory where zig thinks it is installed
511 \\ -dirafter [dir] same as -isystem but do it last
512 \\ -isystem [dir] add additional search path for other .h files
513 \\ -mllvm [arg] additional arguments to forward to LLVM's option processing
514 \\Link Options:
515 \\ --ar-path [path] set the path to ar
516 \\ --dynamic-linker [path] set the path to ld.so
517 \\ --each-lib-rpath add rpath for each used dynamic library
518 \\ --libc-lib-dir [path] directory where libc crt1.o resides
519 \\ --libc-static-lib-dir [path] directory where libc crtbegin.o resides
520 \\ --msvc-lib-dir [path] (windows) directory where vcruntime.lib resides
521 \\ --kernel32-lib-dir [path] (windows) directory where kernel32.lib resides
522 \\ --library [lib] link against lib
523 \\ --library-path [dir] add a directory to the library search path
524 \\ --linker-script [path] use a custom linker script
525 \\ --object [obj] add object file to build
526 \\ -L[dir] alias for --library-path
527 \\ -rdynamic add all symbols to the dynamic symbol table
528 \\ -rpath [path] add directory to the runtime library search path
529 \\ -mconsole (windows) --subsystem console to the linker
530 \\ -mwindows (windows) --subsystem windows to the linker
531 \\ -framework [name] (darwin) link against framework
532 \\ -mios-version-min [ver] (darwin) set iOS deployment target
533 \\ -mmacosx-version-min [ver] (darwin) set Mac OS X deployment target
534 \\ --ver-major [ver] dynamic library semver major version
535 \\ --ver-minor [ver] dynamic library semver minor version
536 \\ --ver-patch [ver] dynamic library semver patch version
537 \\Test Options:
538 \\ --test-filter [text] skip tests that do not match filter
539 \\ --test-name-prefix [text] add prefix to all tests
540 \\ --test-cmd [arg] specify test execution command one arg at a time
541 \\ --test-cmd-bin appends test binary path to test cmd args
542 \\
543 );
544}
57545
58 var tokenizer = Tokenizer.init(target_file_buf);546fn printZen() -> %void {
59 var parser = Parser.init(&tokenizer, allocator, target_file);547 var stdout_file = %return io.getStdErr();
60 defer parser.deinit();548 %return stdout_file.write(
549 \\
550 \\ * Communicate intent precisely.
551 \\ * Edge cases matter.
552 \\ * Favor reading code over writing code.
553 \\ * Only one obvious way to do things.
554 \\ * Runtime crashes are better than bugs.
555 \\ * Compile errors are better than runtime crashes.
556 \\ * Incremental improvements.
557 \\ * Avoid local maximums.
558 \\ * Reduce the amount one must remember.
559 \\ * Minimize energy spent on coding style.
560 \\ * Together we serve end users.
561 \\
562 \\
563 );
564}
565
566/// Caller must free result
567fn resolveZigLibDir(allocator: &mem.Allocator, zig_install_prefix_arg: ?[]const u8) -> %[]u8 {
568 if (zig_install_prefix_arg) |zig_install_prefix| {
569 return testZigInstallPrefix(allocator, zig_install_prefix) %% |err| {
570 warn("No Zig installation found at prefix {}: {}\n", zig_install_prefix_arg, @errorName(err));
571 return error.ZigInstallationNotFound;
572 };
573 } else {
574 return findZigLibDir(allocator) %% |err| {
575 warn("Unable to find zig lib directory: {}.\nReinstall Zig or use --zig-install-prefix.\n",
576 @errorName(err));
577 return error.ZigLibDirNotFound;
578 };
579 }
580}
61581
62 const root_node = %return parser.parse();582/// Caller must free result
63 defer parser.freeAst(root_node);583fn testZigInstallPrefix(allocator: &mem.Allocator, test_path: []const u8) -> %[]u8 {
584 const test_zig_dir = %return os.path.join(allocator, test_path, "lib", "zig");
585 %defer allocator.free(test_zig_dir);
64586
65 %return parser.renderAst(out_stream, root_node);587 const test_index_file = %return os.path.join(allocator, test_zig_dir, "std", "index.zig");
588 defer allocator.free(test_index_file);
66589
67 warn("====fmt:====\n");590 var file = %return io.File.openRead(test_index_file, allocator);
68 %return parser.renderSource(out_stream, root_node);591 file.close();
592
593 return test_zig_dir;
69}594}
70595
71test "import other tests" {596/// Caller must free result
72 _ = @import("parser.zig");597fn findZigLibDir(allocator: &mem.Allocator) -> %[]u8 {
73 _ = @import("tokenizer.zig");598 const self_exe_path = %return os.selfExeDirPath(allocator);
599 defer allocator.free(self_exe_path);
600
601 var cur_path: []const u8 = self_exe_path;
602 while (true) {
603 const test_dir = os.path.dirname(cur_path);
604
605 if (mem.eql(u8, test_dir, cur_path)) {
606 break;
607 }
608
609 return testZigInstallPrefix(allocator, test_dir) %% |err| {
610 cur_path = test_dir;
611 continue;
612 };
613 }
614
615 // TODO look in hard coded installation path from configuration
616 //if (ZIG_INSTALL_PREFIX != nullptr) {
617 // if (test_zig_install_prefix(buf_create_from_str(ZIG_INSTALL_PREFIX), out_path)) {
618 // return 0;
619 // }
620 //}
621
622 return error.FileNotFound;
74}623}
src-self-hosted/module.zig created+295
...@@ -0,0 +1,295 @@
1const std = @import("std");
2const os = std.os;
3const io = std.io;
4const mem = std.mem;
5const Buffer = std.Buffer;
6const llvm = @import("llvm.zig");
7const c = @import("c.zig");
8const builtin = @import("builtin");
9const Target = @import("target.zig").Target;
10const warn = std.debug.warn;
11const Tokenizer = @import("tokenizer.zig").Tokenizer;
12const Token = @import("tokenizer.zig").Token;
13const Parser = @import("parser.zig").Parser;
14const ArrayList = std.ArrayList;
15
16pub const Module = struct {
17 allocator: &mem.Allocator,
18 name: Buffer,
19 root_src_path: ?[]const u8,
20 module: llvm.ModuleRef,
21 context: llvm.ContextRef,
22 builder: llvm.BuilderRef,
23 target: Target,
24 build_mode: builtin.Mode,
25 zig_lib_dir: []const u8,
26
27 version_major: u32,
28 version_minor: u32,
29 version_patch: u32,
30
31 linker_script: ?[]const u8,
32 cache_dir: []const u8,
33 libc_lib_dir: ?[]const u8,
34 libc_static_lib_dir: ?[]const u8,
35 libc_include_dir: ?[]const u8,
36 msvc_lib_dir: ?[]const u8,
37 kernel32_lib_dir: ?[]const u8,
38 dynamic_linker: ?[]const u8,
39 out_h_path: ?[]const u8,
40
41 is_test: bool,
42 each_lib_rpath: bool,
43 strip: bool,
44 is_static: bool,
45 linker_rdynamic: bool,
46
47 clang_argv: []const []const u8,
48 llvm_argv: []const []const u8,
49 lib_dirs: []const []const u8,
50 rpath_list: []const []const u8,
51 assembly_files: []const []const u8,
52 link_objects: []const []const u8,
53
54 windows_subsystem_windows: bool,
55 windows_subsystem_console: bool,
56
57 link_libs_list: ArrayList(&LinkLib),
58 libc_link_lib: ?&LinkLib,
59
60 err_color: ErrColor,
61
62 verbose_tokenize: bool,
63 verbose_ast_tree: bool,
64 verbose_ast_fmt: bool,
65 verbose_cimport: bool,
66 verbose_ir: bool,
67 verbose_llvm_ir: bool,
68 verbose_link: bool,
69
70 darwin_frameworks: []const []const u8,
71 darwin_version_min: DarwinVersionMin,
72
73 test_filters: []const []const u8,
74 test_name_prefix: ?[]const u8,
75
76 emit_file_type: Emit,
77
78 kind: Kind,
79
80 pub const DarwinVersionMin = union(enum) {
81 None,
82 MacOS: []const u8,
83 Ios: []const u8,
84 };
85
86 pub const Kind = enum {
87 Exe,
88 Lib,
89 Obj,
90 };
91
92 pub const ErrColor = enum {
93 Auto,
94 Off,
95 On,
96 };
97
98 pub const LinkLib = struct {
99 name: []const u8,
100 path: ?[]const u8,
101 /// the list of symbols we depend on from this lib
102 symbols: ArrayList([]u8),
103 provided_explicitly: bool,
104 };
105
106 pub const Emit = enum {
107 Binary,
108 Assembly,
109 LlvmIr,
110 };
111
112 pub fn create(allocator: &mem.Allocator, name: []const u8, root_src_path: ?[]const u8, target: &const Target,
113 kind: Kind, build_mode: builtin.Mode, zig_lib_dir: []const u8, cache_dir: []const u8) -> %&Module
114 {
115 var name_buffer = %return Buffer.init(allocator, name);
116 %defer name_buffer.deinit();
117
118 const context = c.LLVMContextCreate() ?? return error.OutOfMemory;
119 %defer c.LLVMContextDispose(context);
120
121 const module = c.LLVMModuleCreateWithNameInContext(name_buffer.ptr(), context) ?? return error.OutOfMemory;
122 %defer c.LLVMDisposeModule(module);
123
124 const builder = c.LLVMCreateBuilderInContext(context) ?? return error.OutOfMemory;
125 %defer c.LLVMDisposeBuilder(builder);
126
127 const module_ptr = %return allocator.create(Module);
128 %defer allocator.destroy(module_ptr);
129
130 *module_ptr = Module {
131 .allocator = allocator,
132 .name = name_buffer,
133 .root_src_path = root_src_path,
134 .module = module,
135 .context = context,
136 .builder = builder,
137 .target = *target,
138 .kind = kind,
139 .build_mode = build_mode,
140 .zig_lib_dir = zig_lib_dir,
141 .cache_dir = cache_dir,
142
143 .version_major = 0,
144 .version_minor = 0,
145 .version_patch = 0,
146
147 .verbose_tokenize = false,
148 .verbose_ast_tree = false,
149 .verbose_ast_fmt = false,
150 .verbose_cimport = false,
151 .verbose_ir = false,
152 .verbose_llvm_ir = false,
153 .verbose_link = false,
154
155 .linker_script = null,
156 .libc_lib_dir = null,
157 .libc_static_lib_dir = null,
158 .libc_include_dir = null,
159 .msvc_lib_dir = null,
160 .kernel32_lib_dir = null,
161 .dynamic_linker = null,
162 .out_h_path = null,
163 .is_test = false,
164 .each_lib_rpath = false,
165 .strip = false,
166 .is_static = false,
167 .linker_rdynamic = false,
168 .clang_argv = [][]const u8{},
169 .llvm_argv = [][]const u8{},
170 .lib_dirs = [][]const u8{},
171 .rpath_list = [][]const u8{},
172 .assembly_files = [][]const u8{},
173 .link_objects = [][]const u8{},
174 .windows_subsystem_windows = false,
175 .windows_subsystem_console = false,
176 .link_libs_list = ArrayList(&LinkLib).init(allocator),
177 .libc_link_lib = null,
178 .err_color = ErrColor.Auto,
179 .darwin_frameworks = [][]const u8{},
180 .darwin_version_min = DarwinVersionMin.None,
181 .test_filters = [][]const u8{},
182 .test_name_prefix = null,
183 .emit_file_type = Emit.Binary,
184 };
185 return module_ptr;
186 }
187
188 fn dump(self: &Module) {
189 c.LLVMDumpModule(self.module);
190 }
191
192 pub fn destroy(self: &Module) {
193 c.LLVMDisposeBuilder(self.builder);
194 c.LLVMDisposeModule(self.module);
195 c.LLVMContextDispose(self.context);
196 self.name.deinit();
197
198 self.allocator.destroy(self);
199 }
200
201 pub fn build(self: &Module) -> %void {
202 const root_src_path = self.root_src_path ?? @panic("TODO handle null root src path");
203 const root_src_real_path = os.path.real(self.allocator, root_src_path) %% |err| {
204 %return printError("unable to open '{}': {}", root_src_path, err);
205 return err;
206 };
207 %defer self.allocator.free(root_src_real_path);
208
209 const source_code = io.readFileAlloc(root_src_real_path, self.allocator) %% |err| {
210 %return printError("unable to open '{}': {}", root_src_real_path, err);
211 return err;
212 };
213 %defer self.allocator.free(source_code);
214
215 warn("====input:====\n");
216
217 warn("{}", source_code);
218
219 warn("====tokenization:====\n");
220 {
221 var tokenizer = Tokenizer.init(source_code);
222 while (true) {
223 const token = tokenizer.next();
224 tokenizer.dump(token);
225 if (token.id == Token.Id.Eof) {
226 break;
227 }
228 }
229 }
230
231 warn("====parse:====\n");
232
233 var tokenizer = Tokenizer.init(source_code);
234 var parser = Parser.init(&tokenizer, self.allocator, root_src_real_path);
235 defer parser.deinit();
236
237 const root_node = %return parser.parse();
238 defer parser.freeAst(root_node);
239
240 var stderr_file = %return std.io.getStdErr();
241 var stderr_file_out_stream = std.io.FileOutStream.init(&stderr_file);
242 const out_stream = &stderr_file_out_stream.stream;
243 %return parser.renderAst(out_stream, root_node);
244
245 warn("====fmt:====\n");
246 %return parser.renderSource(out_stream, root_node);
247
248 warn("====ir:====\n");
249 warn("TODO\n\n");
250
251 warn("====llvm ir:====\n");
252 self.dump();
253
254 }
255
256 pub fn link(self: &Module, out_file: ?[]const u8) -> %void {
257 warn("TODO link");
258 }
259
260 pub fn addLinkLib(self: &Module, name: []const u8, provided_explicitly: bool) -> %&LinkLib {
261 const is_libc = mem.eql(u8, name, "c");
262
263 if (is_libc) {
264 if (self.libc_link_lib) |libc_link_lib| {
265 return libc_link_lib;
266 }
267 }
268
269 for (self.link_libs_list.toSliceConst()) |existing_lib| {
270 if (mem.eql(u8, name, existing_lib.name)) {
271 return existing_lib;
272 }
273 }
274
275 const link_lib = %return self.allocator.create(LinkLib);
276 *link_lib = LinkLib {
277 .name = name,
278 .path = null,
279 .provided_explicitly = provided_explicitly,
280 .symbols = ArrayList([]u8).init(self.allocator),
281 };
282 %return self.link_libs_list.append(link_lib);
283 if (is_libc) {
284 self.libc_link_lib = link_lib;
285 }
286 return link_lib;
287 }
288};
289
290fn printError(comptime format: []const u8, args: ...) -> %void {
291 var stderr_file = %return std.io.getStdErr();
292 var stderr_file_out_stream = std.io.FileOutStream.init(&stderr_file);
293 const out_stream = &stderr_file_out_stream.stream;
294 %return out_stream.print(format, args);
295}
src-self-hosted/target.zig+51
...@@ -1,5 +1,56 @@...@@ -1,5 +1,56 @@
1const builtin = @import("builtin");
1const c = @import("c.zig");2const c = @import("c.zig");
23
4pub const CrossTarget = struct {
5 arch: builtin.Arch,
6 os: builtin.Os,
7 environ: builtin.Environ,
8};
9
10pub const Target = union(enum) {
11 Native,
12 Cross: CrossTarget,
13
14 pub fn oFileExt(self: &const Target) -> []const u8 {
15 const environ = switch (*self) {
16 Target.Native => builtin.environ,
17 Target.Cross => |t| t.environ,
18 };
19 return switch (environ) {
20 builtin.Environ.msvc => ".obj",
21 else => ".o",
22 };
23 }
24
25 pub fn exeFileExt(self: &const Target) -> []const u8 {
26 return switch (self.getOs()) {
27 builtin.Os.windows => ".exe",
28 else => "",
29 };
30 }
31
32 pub fn getOs(self: &const Target) -> builtin.Os {
33 return switch (*self) {
34 Target.Native => builtin.os,
35 Target.Cross => |t| t.os,
36 };
37 }
38
39 pub fn isDarwin(self: &const Target) -> bool {
40 return switch (self.getOs()) {
41 builtin.Os.darwin, builtin.Os.ios, builtin.Os.macosx => true,
42 else => false,
43 };
44 }
45
46 pub fn isWindows(self: &const Target) -> bool {
47 return switch (self.getOs()) {
48 builtin.Os.windows => true,
49 else => false,
50 };
51 }
52};
53
3pub fn initializeAll() {54pub fn initializeAll() {
4 c.LLVMInitializeAllTargets();55 c.LLVMInitializeAllTargets();
5 c.LLVMInitializeAllTargetInfos();56 c.LLVMInitializeAllTargetInfos();
std/buffer.zig+5
...@@ -139,6 +139,11 @@ pub const Buffer = struct {...@@ -139,6 +139,11 @@ pub const Buffer = struct {
139 %return self.resize(m.len);139 %return self.resize(m.len);
140 mem.copy(u8, self.list.toSlice(), m);140 mem.copy(u8, self.list.toSlice(), m);
141 }141 }
142
143 /// For passing to C functions.
144 pub fn ptr(self: &const Buffer) -> &u8 {
145 return self.list.items.ptr;
146 }
142};147};
143148
144test "simple Buffer" {149test "simple Buffer" {
std/c/index.zig+1
...@@ -48,3 +48,4 @@ pub extern "c" fn setregid(rgid: c_uint, egid: c_uint) -> c_int;...@@ -48,3 +48,4 @@ pub extern "c" fn setregid(rgid: c_uint, egid: c_uint) -> c_int;
48pub extern "c" fn malloc(usize) -> ?&c_void;48pub extern "c" fn malloc(usize) -> ?&c_void;
49pub extern "c" fn realloc(&c_void, usize) -> ?&c_void;49pub extern "c" fn realloc(&c_void, usize) -> ?&c_void;
50pub extern "c" fn free(&c_void);50pub extern "c" fn free(&c_void);
51pub extern "c" fn posix_memalign(memptr: &&c_void, alignment: usize, size: usize) -> c_int;
std/heap.zig+7-8
...@@ -10,7 +10,8 @@ const Allocator = mem.Allocator;...@@ -10,7 +10,8 @@ const Allocator = mem.Allocator;
1010
11error OutOfMemory;11error OutOfMemory;
1212
13pub var c_allocator = Allocator {13pub const c_allocator = &c_allocator_state;
14var c_allocator_state = Allocator {
14 .allocFn = cAlloc,15 .allocFn = cAlloc,
15 .reallocFn = cRealloc,16 .reallocFn = cRealloc,
16 .freeFn = cFree,17 .freeFn = cFree,
...@@ -24,15 +25,13 @@ fn cAlloc(self: &Allocator, n: usize, alignment: u29) -> %[]u8 {...@@ -24,15 +25,13 @@ fn cAlloc(self: &Allocator, n: usize, alignment: u29) -> %[]u8 {
24}25}
2526
26fn cRealloc(self: &Allocator, old_mem: []u8, new_size: usize, alignment: u29) -> %[]u8 {27fn cRealloc(self: &Allocator, old_mem: []u8, new_size: usize, alignment: u29) -> %[]u8 {
27 if (new_size <= old_mem.len) {28 const old_ptr = @ptrCast(&c_void, old_mem.ptr);
29 if (c.realloc(old_ptr, new_size)) |buf| {
30 return @ptrCast(&u8, buf)[0..new_size];
31 } else if (new_size <= old_mem.len) {
28 return old_mem[0..new_size];32 return old_mem[0..new_size];
29 } else {33 } else {
30 const old_ptr = @ptrCast(&c_void, old_mem.ptr);34 return error.OutOfMemory;
31 if (c.realloc(old_ptr, usize(new_size))) |buf| {
32 return @ptrCast(&u8, buf)[0..new_size];
33 } else {
34 return error.OutOfMemory;
35 }
36 }35 }
37}36}
3837
std/os/index.zig+33
...@@ -1543,6 +1543,39 @@ pub fn openSelfExe() -> %io.File {...@@ -1543,6 +1543,39 @@ pub fn openSelfExe() -> %io.File {
1543 }1543 }
1544}1544}
15451545
1546/// Get the directory path that contains the current executable.
1547/// Caller owns returned memory.
1548pub fn selfExeDirPath(allocator: &mem.Allocator) -> %[]u8 {
1549 switch (builtin.os) {
1550 Os.linux => {
1551 // If the currently executing binary has been deleted,
1552 // the file path looks something like `/a/b/c/exe (deleted)`
1553 // This path cannot be opened, but it's valid for determining the directory
1554 // the executable was in when it was run.
1555 const full_exe_path = %return readLink(allocator, "/proc/self/exe");
1556 %defer allocator.free(full_exe_path);
1557 const dir = path.dirname(full_exe_path);
1558 return allocator.shrink(u8, full_exe_path, dir.len);
1559 },
1560 Os.windows => {
1561 @panic("TODO windows std.os.selfExeDirPath");
1562 //buf_resize(out_path, 256);
1563 //for (;;) {
1564 // DWORD copied_amt = GetModuleFileName(nullptr, buf_ptr(out_path), buf_len(out_path));
1565 // if (copied_amt <= 0) {
1566 // return ErrorFileNotFound;
1567 // }
1568 // if (copied_amt < buf_len(out_path)) {
1569 // buf_resize(out_path, copied_amt);
1570 // return 0;
1571 // }
1572 // buf_resize(out_path, buf_len(out_path) * 2);
1573 //}
1574 },
1575 else => @compileError("unimplemented: std.os.selfExeDirPath for " ++ @tagName(builtin.os)),
1576 }
1577}
1578
1546pub fn isTty(handle: FileHandle) -> bool {1579pub fn isTty(handle: FileHandle) -> bool {
1547 if (is_windows) {1580 if (is_windows) {
1548 return windows_util.windowsIsTty(handle);1581 return windows_util.windowsIsTty(handle);