authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-09-18 01:33:32-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-09-18 01:33:32-07:00
logdc79651e6a46dc050976feabbb1b5e25a68dcf3f
tree9a2833b5e06778d60ffcabde7bdba37be2498b53
parenta9b18023a4c33a0563fca2aa20a239e3ee38927a

stage2: add CLI for `zig translate-c`


5 files changed, 93 insertions(+), 35 deletions(-)

BRANCH_TODO-1
...@@ -1,4 +1,3 @@...@@ -1,4 +1,3 @@
1 * `zig translate-c`
2 * `zig test`1 * `zig test`
3 * `zig build`2 * `zig build`
4 * `-ftime-report`3 * `-ftime-report`
CMakeLists.txt+9-17
...@@ -392,15 +392,18 @@ if(ZIG_TEST_COVERAGE)...@@ -392,15 +392,18 @@ if(ZIG_TEST_COVERAGE)
392 set(EXE_LDFLAGS "${EXE_LDFLAGS} -fprofile-arcs -ftest-coverage")392 set(EXE_LDFLAGS "${EXE_LDFLAGS} -fprofile-arcs -ftest-coverage")
393endif()393endif()
394394
395add_library(zig_cpp STATIC ${ZIG_CPP_SOURCES})395add_library(zig_cpp STATIC ${ZIG_SOURCES} ${ZIG_CPP_SOURCES})
396set_target_properties(zig_cpp PROPERTIES396set_target_properties(zig_cpp PROPERTIES
397 COMPILE_FLAGS ${EXE_CFLAGS}397 COMPILE_FLAGS ${EXE_CFLAGS}
398)398)
399399
400target_link_libraries(zig_cpp LINK_PUBLIC400target_link_libraries(zig_cpp LINK_PUBLIC
401 opt_c_util
402 ${SOFTFLOAT_LIBRARIES}
401 ${CLANG_LIBRARIES}403 ${CLANG_LIBRARIES}
402 ${LLD_LIBRARIES}404 ${LLD_LIBRARIES}
403 ${LLVM_LIBRARIES}405 ${LLVM_LIBRARIES}
406 ${CMAKE_THREAD_LIBS_INIT}
404)407)
405if(ZIG_WORKAROUND_POLLY_SO)408if(ZIG_WORKAROUND_POLLY_SO)
406 target_link_libraries(zig_cpp LINK_PUBLIC "-Wl,${ZIG_WORKAROUND_POLLY_SO}")409 target_link_libraries(zig_cpp LINK_PUBLIC "-Wl,${ZIG_WORKAROUND_POLLY_SO}")
...@@ -411,27 +414,16 @@ set_target_properties(opt_c_util PROPERTIES...@@ -411,27 +414,16 @@ set_target_properties(opt_c_util PROPERTIES
411 COMPILE_FLAGS "${OPTIMIZED_C_FLAGS}"414 COMPILE_FLAGS "${OPTIMIZED_C_FLAGS}"
412)415)
413416
414add_library(zigcompiler STATIC ${ZIG_SOURCES})
415set_target_properties(zigcompiler PROPERTIES
416 COMPILE_FLAGS ${EXE_CFLAGS}
417 LINK_FLAGS ${EXE_LDFLAGS}
418)
419target_link_libraries(zigcompiler LINK_PUBLIC
420 zig_cpp
421 opt_c_util
422 ${SOFTFLOAT_LIBRARIES}
423 ${CMAKE_THREAD_LIBS_INIT}
424)
425if(NOT MSVC)417if(NOT MSVC)
426 target_link_libraries(zigcompiler LINK_PUBLIC ${LIBXML2})418 target_link_libraries(zig_cpp LINK_PUBLIC ${LIBXML2})
427endif()419endif()
428420
429if(ZIG_DIA_GUIDS_LIB)421if(ZIG_DIA_GUIDS_LIB)
430 target_link_libraries(zigcompiler LINK_PUBLIC ${ZIG_DIA_GUIDS_LIB})422 target_link_libraries(zig_cpp LINK_PUBLIC ${ZIG_DIA_GUIDS_LIB})
431endif()423endif()
432424
433if(MSVC OR MINGW)425if(MSVC OR MINGW)
434 target_link_libraries(zigcompiler LINK_PUBLIC version)426 target_link_libraries(zig_cpp LINK_PUBLIC version)
435endif()427endif()
436428
437add_executable(zig0 ${ZIG0_SOURCES})429add_executable(zig0 ${ZIG0_SOURCES})
...@@ -439,7 +431,7 @@ set_target_properties(zig0 PROPERTIES...@@ -439,7 +431,7 @@ set_target_properties(zig0 PROPERTIES
439 COMPILE_FLAGS ${EXE_CFLAGS}431 COMPILE_FLAGS ${EXE_CFLAGS}
440 LINK_FLAGS ${EXE_LDFLAGS}432 LINK_FLAGS ${EXE_LDFLAGS}
441)433)
442target_link_libraries(zig0 zigcompiler)434target_link_libraries(zig0 zig_cpp)
443435
444if(MSVC)436if(MSVC)
445 set(ZIG1_OBJECT "${CMAKE_BINARY_DIR}/zig1.obj")437 set(ZIG1_OBJECT "${CMAKE_BINARY_DIR}/zig1.obj")
...@@ -493,7 +485,7 @@ set_target_properties(zig PROPERTIES...@@ -493,7 +485,7 @@ set_target_properties(zig PROPERTIES
493 COMPILE_FLAGS ${EXE_CFLAGS}485 COMPILE_FLAGS ${EXE_CFLAGS}
494 LINK_FLAGS ${EXE_LDFLAGS}486 LINK_FLAGS ${EXE_LDFLAGS}
495)487)
496target_link_libraries(zig zigcompiler "${ZIG1_OBJECT}")488target_link_libraries(zig "${ZIG1_OBJECT}" zig_cpp)
497if(MSVC)489if(MSVC)
498 target_link_libraries(zig ntdll.lib)490 target_link_libraries(zig ntdll.lib)
499elseif(MINGW)491elseif(MINGW)
src-self-hosted/Compilation.zig+12-8
...@@ -1005,7 +1005,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject) !void {...@@ -1005,7 +1005,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject) !void {
1005 defer tracy.end();1005 defer tracy.end();
10061006
1007 if (!build_options.have_llvm) {1007 if (!build_options.have_llvm) {
1008 return comp.failCObj(c_object, "clang not available: compiler not built with LLVM extensions enabled", .{});1008 return comp.failCObj(c_object, "clang not available: compiler built without LLVM extensions", .{});
1009 }1009 }
1010 const self_exe_path = comp.self_exe_path orelse1010 const self_exe_path = comp.self_exe_path orelse
1011 return comp.failCObj(c_object, "clang compilation disabled", .{});1011 return comp.failCObj(c_object, "clang compilation disabled", .{});
...@@ -1081,10 +1081,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject) !void {...@@ -1081,10 +1081,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject) !void {
1081 try argv.appendSlice(c_object.src.extra_flags);1081 try argv.appendSlice(c_object.src.extra_flags);
10821082
1083 if (comp.verbose_cc) {1083 if (comp.verbose_cc) {
1084 for (argv.items[0 .. argv.items.len - 1]) |arg| {1084 dump_argv(argv.items);
1085 std.debug.print("{} ", .{arg});
1086 }
1087 std.debug.print("{}\n", .{argv.items[argv.items.len - 1]});
1088 }1085 }
10891086
1090 const child = try std.ChildProcess.init(argv.items, arena);1087 const child = try std.ChildProcess.init(argv.items, arena);
...@@ -1190,7 +1187,7 @@ fn tmpFilePath(comp: *Compilation, arena: *Allocator, suffix: []const u8) error{...@@ -1190,7 +1187,7 @@ fn tmpFilePath(comp: *Compilation, arena: *Allocator, suffix: []const u8) error{
1190}1187}
11911188
1192/// Add common C compiler args between translate-c and C object compilation.1189/// Add common C compiler args between translate-c and C object compilation.
1193fn addCCArgs(1190pub fn addCCArgs(
1194 comp: *Compilation,1191 comp: *Compilation,
1195 arena: *Allocator,1192 arena: *Allocator,
1196 argv: *std.ArrayList([]const u8),1193 argv: *std.ArrayList([]const u8),
...@@ -1671,12 +1668,19 @@ fn wantBuildLibUnwindFromSource(comp: *Compilation) bool {...@@ -1671,12 +1668,19 @@ fn wantBuildLibUnwindFromSource(comp: *Compilation) bool {
1671}1668}
16721669
1673fn updateBuiltinZigFile(comp: *Compilation, mod: *Module) !void {1670fn updateBuiltinZigFile(comp: *Compilation, mod: *Module) !void {
1674 const source = try comp.generateBuiltinZigSource();1671 const source = try comp.generateBuiltinZigSource(comp.gpa);
1675 defer comp.gpa.free(source);1672 defer comp.gpa.free(source);
1676 try mod.zig_cache_artifact_directory.handle.writeFile("builtin.zig", source);1673 try mod.zig_cache_artifact_directory.handle.writeFile("builtin.zig", source);
1677}1674}
16781675
1679pub fn generateBuiltinZigSource(comp: *Compilation) ![]u8 {1676pub fn dump_argv(argv: []const []const u8) void {
1677 for (argv[0 .. argv.len - 1]) |arg| {
1678 std.debug.print("{} ", .{arg});
1679 }
1680 std.debug.print("{}\n", .{argv[argv.len - 1]});
1681}
1682
1683pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) ![]u8 {
1680 var buffer = std.ArrayList(u8).init(comp.gpa);1684 var buffer = std.ArrayList(u8).init(comp.gpa);
1681 defer buffer.deinit();1685 defer buffer.deinit();
16821686
src-self-hosted/main.zig+70-7
...@@ -15,6 +15,7 @@ const build_options = @import("build_options");...@@ -15,6 +15,7 @@ const build_options = @import("build_options");
15const warn = std.log.warn;15const warn = std.log.warn;
16const introspect = @import("introspect.zig");16const introspect = @import("introspect.zig");
17const LibCInstallation = @import("libc_installation.zig").LibCInstallation;17const LibCInstallation = @import("libc_installation.zig").LibCInstallation;
18const translate_c = @import("translate_c.zig");
1819
19pub fn fatal(comptime format: []const u8, args: anytype) noreturn {20pub fn fatal(comptime format: []const u8, args: anytype) noreturn {
20 std.log.emerg(format, args);21 std.log.emerg(format, args);
...@@ -864,6 +865,10 @@ pub fn buildOutputType(...@@ -864,6 +865,10 @@ pub fn buildOutputType(
864 }865 }
865 }866 }
866867
868 if (arg_mode == .translate_c and c_source_files.items.len != 1) {
869 fatal("translate-c expects exactly 1 source file (found {})", .{c_source_files.items.len});
870 }
871
867 const root_name = if (provided_name) |n| n else blk: {872 const root_name = if (provided_name) |n| n else blk: {
868 if (root_src_file) |file| {873 if (root_src_file) |file| {
869 const basename = fs.path.basename(file);874 const basename = fs.path.basename(file);
...@@ -1175,10 +1180,10 @@ pub fn buildOutputType(...@@ -1175,10 +1180,10 @@ pub fn buildOutputType(
1175 defer comp.destroy();1180 defer comp.destroy();
11761181
1177 if (show_builtin) {1182 if (show_builtin) {
1178 const source = try comp.generateBuiltinZigSource();1183 return std.io.getStdOut().writeAll(try comp.generateBuiltinZigSource(arena));
1179 defer comp.gpa.free(source);1184 }
1180 try std.io.getStdOut().writeAll(source);1185 if (arg_mode == .translate_c) {
1181 return;1186 return cmdTranslateC(comp, arena);
1182 }1187 }
11831188
1184 try updateModule(gpa, comp, zir_out_path);1189 try updateModule(gpa, comp, zir_out_path);
...@@ -1248,6 +1253,63 @@ fn updateModule(gpa: *Allocator, comp: *Compilation, zir_out_path: ?[]const u8)...@@ -1248,6 +1253,63 @@ fn updateModule(gpa: *Allocator, comp: *Compilation, zir_out_path: ?[]const u8)
1248 }1253 }
1249}1254}
12501255
1256fn cmdTranslateC(comp: *Compilation, arena: *Allocator) !void {
1257 if (!build_options.have_llvm)
1258 fatal("cannot translate-c: compiler built without LLVM extensions", .{});
1259
1260 assert(comp.c_source_files.len == 1);
1261
1262 var argv = std.ArrayList([]const u8).init(arena);
1263
1264 const c_source_file = comp.c_source_files[0];
1265 const file_ext = Compilation.classifyFileExt(c_source_file.src_path);
1266 try comp.addCCArgs(arena, &argv, file_ext, true, null);
1267 try argv.append(c_source_file.src_path);
1268
1269 if (comp.verbose_cc) {
1270 std.debug.print("clang ", .{});
1271 Compilation.dump_argv(argv.items);
1272 }
1273
1274 // Convert to null terminated args.
1275 const new_argv_with_sentinel = try arena.alloc(?[*:0]const u8, argv.items.len + 1);
1276 new_argv_with_sentinel[argv.items.len] = null;
1277 const new_argv = new_argv_with_sentinel[0..argv.items.len :null];
1278 for (argv.items) |arg, i| {
1279 new_argv[i] = try arena.dupeZ(u8, arg);
1280 }
1281
1282 const c_headers_dir_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{"include"});
1283 const c_headers_dir_path_z = try arena.dupeZ(u8, c_headers_dir_path);
1284 var clang_errors: []translate_c.ClangErrMsg = &[0]translate_c.ClangErrMsg{};
1285 const tree = translate_c.translate(
1286 comp.gpa,
1287 new_argv.ptr,
1288 new_argv.ptr + new_argv.len,
1289 &clang_errors,
1290 c_headers_dir_path_z,
1291 ) catch |err| switch (err) {
1292 error.OutOfMemory => return error.OutOfMemory,
1293 error.ASTUnitFailure => fatal("clang API returned errors but due to a clang bug, it is not exposing the errors for zig to see. For more details: https://github.com/ziglang/zig/issues/4455", .{}),
1294 error.SemanticAnalyzeFail => {
1295 for (clang_errors) |clang_err| {
1296 std.debug.print("{}:{}:{}: {}\n", .{
1297 if (clang_err.filename_ptr) |p| p[0..clang_err.filename_len] else "(no file)",
1298 clang_err.line + 1,
1299 clang_err.column + 1,
1300 clang_err.msg_ptr[0..clang_err.msg_len],
1301 });
1302 }
1303 process.exit(1);
1304 },
1305 };
1306 defer tree.deinit();
1307
1308 var bos = io.bufferedOutStream(io.getStdOut().writer());
1309 _ = try std.zig.render(comp.gpa, bos.writer(), tree);
1310 try bos.flush();
1311}
1312
1251pub const usage_libc =1313pub const usage_libc =
1252 \\Usage: zig libc1314 \\Usage: zig libc
1253 \\1315 \\
...@@ -1401,8 +1463,9 @@ pub fn cmdFmt(gpa: *Allocator, args: []const []const u8) !void {...@@ -1401,8 +1463,9 @@ pub fn cmdFmt(gpa: *Allocator, args: []const []const u8) !void {
1401 process.exit(code);1463 process.exit(code);
1402 }1464 }
14031465
1404 const stdout = io.getStdOut().outStream();1466 var bos = io.bufferedOutStream(io.getStdOut().writer());
1405 _ = try std.zig.render(gpa, stdout, tree);1467 _ = try std.zig.render(gpa, bos.writer(), tree);
1468 try bos.flush();
1406 return;1469 return;
1407 }1470 }
14081471
...@@ -1644,7 +1707,7 @@ extern "c" fn ZigClang_main(argc: c_int, argv: [*:null]?[*:0]u8) c_int;...@@ -1644,7 +1707,7 @@ extern "c" fn ZigClang_main(argc: c_int, argv: [*:null]?[*:0]u8) c_int;
1644/// TODO https://github.com/ziglang/zig/issues/32571707/// TODO https://github.com/ziglang/zig/issues/3257
1645fn punt_to_clang(arena: *Allocator, args: []const []const u8) error{OutOfMemory} {1708fn punt_to_clang(arena: *Allocator, args: []const []const u8) error{OutOfMemory} {
1646 if (!build_options.have_llvm)1709 if (!build_options.have_llvm)
1647 fatal("`zig cc` and `zig c++` unavailable: compiler not built with LLVM extensions enabled", .{});1710 fatal("`zig cc` and `zig c++` unavailable: compiler built without LLVM extensions", .{});
1648 // Convert the args to the format Clang expects.1711 // Convert the args to the format Clang expects.
1649 const argv = try arena.alloc(?[*:0]u8, args.len + 1);1712 const argv = try arena.alloc(?[*:0]u8, args.len + 1);
1650 for (args) |arg, i| {1713 for (args) |arg, i| {
src-self-hosted/translate_c.zig+2-2
...@@ -1,5 +1,5 @@...@@ -1,5 +1,5 @@
1// This is the userland implementation of translate-c which is used by both stage11//! This is the userland implementation of translate-c which is used by both stage1
2// and stage2.2//! and stage2.
33
4const std = @import("std");4const std = @import("std");
5const assert = std.debug.assert;5const assert = std.debug.assert;