diff --git a/src-self-hosted/clang_options_data.zig b/src-self-hosted/clang_options_data.zig index d8bd02043..6dec81493 100644 --- a/src-self-hosted/clang_options_data.zig +++ b/src-self-hosted/clang_options_data.zig @@ -7,7 +7,7 @@ flagpd1("CC"), .{ .name = "E", .syntax = .flag, - .zig_equivalent = .preprocess, + .zig_equivalent = .pp_or_asm, .pd1 = true, .pd2 = false, .psl = false, @@ -53,7 +53,7 @@ flagpd1("Qy"), .{ .name = "S", .syntax = .flag, - .zig_equivalent = .driver_punt, + .zig_equivalent = .pp_or_asm, .pd1 = true, .pd2 = false, .psl = false, @@ -154,7 +154,7 @@ sepd1("Zlinker-input"), .{ .name = "E", .syntax = .flag, - .zig_equivalent = .preprocess, + .zig_equivalent = .pp_or_asm, .pd1 = true, .pd2 = false, .psl = true, @@ -1442,7 +1442,7 @@ sepd1("Zlinker-input"), .{ .name = "assemble", .syntax = .flag, - .zig_equivalent = .driver_punt, + .zig_equivalent = .pp_or_asm, .pd1 = false, .pd2 = true, .psl = false, @@ -1770,7 +1770,7 @@ sepd1("Zlinker-input"), .{ .name = "preprocess", .syntax = .flag, - .zig_equivalent = .preprocess, + .zig_equivalent = .pp_or_asm, .pd1 = false, .pd2 = true, .psl = false, diff --git a/src-self-hosted/stage2.zig b/src-self-hosted/stage2.zig index 8dd2ee876..56f608c28 100644 --- a/src-self-hosted/stage2.zig +++ b/src-self-hosted/stage2.zig @@ -1280,7 +1280,7 @@ pub const ClangArgIterator = extern struct { shared, rdynamic, wl, - preprocess, + pp_or_asm, optimize, debug, sanitize, diff --git a/src/all_types.hpp b/src/all_types.hpp index c0d728124..efb2cd1f0 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -54,6 +54,16 @@ struct ResultLocCast; struct ResultLocReturn; struct IrExecutableGen; +enum FileExt { + FileExtUnknown, + FileExtAsm, + FileExtC, + FileExtCpp, + FileExtHeader, + FileExtLLVMIr, + FileExtLLVMBitCode, +}; + enum PtrLen { PtrLenUnknown, PtrLenSingle, diff --git a/src/analyze.hpp b/src/analyze.hpp index ee069427b..ae010c87e 100644 --- a/src/analyze.hpp +++ b/src/analyze.hpp @@ -257,14 +257,8 @@ Error create_c_object_cache(CodeGen *g, CacheHash **out_cache_hash, bool verbose LLVMTypeRef get_llvm_type(CodeGen *g, ZigType *type); ZigLLVMDIType *get_llvm_di_type(CodeGen *g, ZigType *type); -enum CSourceKind { - CSourceKindAsm, - CSourceKindC, - CSourceKindCpp, -}; - void add_cc_args(CodeGen *g, ZigList &args, const char *out_dep_path, bool translate_c, - CSourceKind source_kind); + FileExt source_kind); void src_assert(bool ok, AstNode *source_node); bool is_container(ZigType *type_entry); diff --git a/src/buffer.hpp b/src/buffer.hpp index 82bcb5661..887631658 100644 --- a/src/buffer.hpp +++ b/src/buffer.hpp @@ -178,10 +178,7 @@ static inline bool buf_starts_with_str(Buf *buf, const char *str) { } static inline bool buf_ends_with_mem(Buf *buf, const char *mem, size_t mem_len) { - if (buf_len(buf) < mem_len) { - return false; - } - return memcmp(buf_ptr(buf) + buf_len(buf) - mem_len, mem, mem_len) == 0; + return mem_ends_with_mem(buf_ptr(buf), buf_len(buf), mem, mem_len); } static inline bool buf_ends_with_str(Buf *buf, const char *str) { diff --git a/src/codegen.cpp b/src/codegen.cpp index 1bc80c8dc..5ead5f7d7 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -9170,20 +9170,13 @@ static void detect_libc(CodeGen *g) { // does not add the "cc" arg void add_cc_args(CodeGen *g, ZigList &args, const char *out_dep_path, - bool translate_c, CSourceKind source_kind) + bool translate_c, FileExt source_kind) { if (translate_c) { args.append("-x"); args.append("c"); } - if (source_kind != CSourceKindAsm && out_dep_path != nullptr) { - args.append("-MD"); - args.append("-MV"); - args.append("-MF"); - args.append(out_dep_path); - } - args.append("-nostdinc"); args.append("-fno-spell-checking"); @@ -9191,14 +9184,7 @@ void add_cc_args(CodeGen *g, ZigList &args, const char *out_dep_pa args.append("-ffunction-sections"); } - if (translate_c) { - if (source_kind != CSourceKindAsm) { - // this gives us access to preprocessing entities, presumably at - // the cost of performance - args.append("-Xclang"); - args.append("-detailed-preprocessing-record"); - } - } else { + if (!translate_c) { switch (g->err_color) { case ErrColorAuto: break; @@ -9232,24 +9218,25 @@ void add_cc_args(CodeGen *g, ZigList &args, const char *out_dep_pa args.append("-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS"); } - // According to Rich Felker libc headers are supposed to go before C language headers. - // However as noted by @dimenus, appending libc headers before c_headers breaks intrinsics - // and other compiler specific items. - args.append("-isystem"); - args.append(buf_ptr(g->zig_c_headers_dir)); - - for (size_t i = 0; i < g->libc_include_dir_len; i += 1) { - const char *include_dir = g->libc_include_dir_list[i]; - args.append("-isystem"); - args.append(include_dir); - } - args.append("-target"); args.append(buf_ptr(&g->llvm_triple_str)); switch (source_kind) { - case CSourceKindC: - case CSourceKindCpp: + case FileExtC: + case FileExtCpp: + case FileExtHeader: + // According to Rich Felker libc headers are supposed to go before C language headers. + // However as noted by @dimenus, appending libc headers before c_headers breaks intrinsics + // and other compiler specific items. + args.append("-isystem"); + args.append(buf_ptr(g->zig_c_headers_dir)); + + for (size_t i = 0; i < g->libc_include_dir_len; i += 1) { + const char *include_dir = g->libc_include_dir_list[i]; + args.append("-isystem"); + args.append(include_dir); + } + if (g->zig_target->llvm_cpu_name != nullptr) { args.append("-Xclang"); args.append("-target-cpu"); @@ -9262,8 +9249,23 @@ void add_cc_args(CodeGen *g, ZigList &args, const char *out_dep_pa args.append("-Xclang"); args.append(g->zig_target->llvm_cpu_features); } + if (translate_c) { + // this gives us access to preprocessing entities, presumably at + // the cost of performance + args.append("-Xclang"); + args.append("-detailed-preprocessing-record"); + } + if (out_dep_path != nullptr) { + args.append("-MD"); + args.append("-MV"); + args.append("-MF"); + args.append(out_dep_path); + } break; - case CSourceKindAsm: + case FileExtAsm: + case FileExtLLVMIr: + case FileExtLLVMBitCode: + case FileExtUnknown: break; } for (size_t i = 0; i < g->zig_target->llvm_cpu_features_asm_len; i += 1) { @@ -9413,7 +9415,7 @@ void codegen_translate_c(CodeGen *g, Buf *full_path) { } ZigList clang_argv = {0}; - add_cc_args(g, clang_argv, out_dep_path_cstr, true, CSourceKindC); + add_cc_args(g, clang_argv, out_dep_path_cstr, true, FileExtC); clang_argv.append(buf_ptr(full_path)); @@ -9751,15 +9753,6 @@ static void gen_c_object(CodeGen *g, Buf *self_exe_path, CFile *c_file) { Buf *c_source_basename = buf_alloc(); os_path_split(c_source_file, nullptr, c_source_basename); - CSourceKind c_source_kind; - if (buf_ends_with_str(c_source_basename, ".s") || - buf_ends_with_str(c_source_basename, ".S")) - { - c_source_kind = CSourceKindAsm; - } else { - c_source_kind = CSourceKindC; - } - Stage2ProgressNode *child_prog_node = stage2_progress_start(g->sub_progress_node, buf_ptr(c_source_basename), buf_len(c_source_basename), 0); @@ -9825,14 +9818,13 @@ static void gen_c_object(CodeGen *g, Buf *self_exe_path, CFile *c_file) { args.append(buf_ptr(self_exe_path)); args.append("clang"); - if (c_file->preprocessor_only_basename != nullptr) { - args.append("-E"); - } else { + if (c_file->preprocessor_only_basename == nullptr) { args.append("-c"); } Buf *out_dep_path = buf_sprintf("%s.d", buf_ptr(out_obj_path)); - add_cc_args(g, args, buf_ptr(out_dep_path), false, c_source_kind); + FileExt ext = classify_file_ext(buf_ptr(c_source_basename), buf_len(c_source_basename)); + add_cc_args(g, args, buf_ptr(out_dep_path), false, ext); args.append("-o"); args.append(buf_ptr(out_obj_path)); diff --git a/src/compiler.cpp b/src/compiler.cpp index cddecc202..8294fc787 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -164,3 +164,25 @@ Buf *get_global_cache_dir(void) { buf_deinit(&app_data_dir); return &saved_global_cache_dir; } + +FileExt classify_file_ext(const char *filename_ptr, size_t filename_len) { + if (mem_ends_with_str(filename_ptr, filename_len, ".c")) { + return FileExtC; + } else if (mem_ends_with_str(filename_ptr, filename_len, ".C") || + mem_ends_with_str(filename_ptr, filename_len, ".cc") || + mem_ends_with_str(filename_ptr, filename_len, ".cpp") || + mem_ends_with_str(filename_ptr, filename_len, ".cxx")) + { + return FileExtCpp; + } else if (mem_ends_with_str(filename_ptr, filename_len, ".ll")) { + return FileExtLLVMIr; + } else if (mem_ends_with_str(filename_ptr, filename_len, ".bc")) { + return FileExtLLVMBitCode; + } else if (mem_ends_with_str(filename_ptr, filename_len, ".s") || + mem_ends_with_str(filename_ptr, filename_len, ".S")) + { + return FileExtAsm; + } + // TODO look for .so, .so.X, .so.X.Y, .so.X.Y.Z + return FileExtUnknown; +} diff --git a/src/compiler.hpp b/src/compiler.hpp index 47841af5d..ae2e6e9c5 100644 --- a/src/compiler.hpp +++ b/src/compiler.hpp @@ -8,8 +8,7 @@ #ifndef ZIG_COMPILER_HPP #define ZIG_COMPILER_HPP -#include "buffer.hpp" -#include "error.hpp" +#include "all_types.hpp" Error get_compiler_id(Buf **result); @@ -19,4 +18,7 @@ Buf *get_zig_std_dir(Buf *zig_lib_dir); Buf *get_global_cache_dir(void); + +FileExt classify_file_ext(const char *filename_ptr, size_t filename_len); + #endif diff --git a/src/ir.cpp b/src/ir.cpp index 5b86922be..2f9e3638f 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -25171,7 +25171,7 @@ static IrInstGen *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstSrcCImpo ZigList clang_argv = {0}; - add_cc_args(ira->codegen, clang_argv, buf_ptr(tmp_dep_file), true, CSourceKindC); + add_cc_args(ira->codegen, clang_argv, buf_ptr(tmp_dep_file), true, FileExtC); clang_argv.append(buf_ptr(&tmp_c_file_path)); diff --git a/src/main.cpp b/src/main.cpp index c95a51221..e9babe562 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -455,7 +455,7 @@ static int main0(int argc, char **argv) { const char *mcpu = nullptr; CodeModel code_model = CodeModelDefault; const char *override_soname = nullptr; - bool only_preprocess = false; + bool only_pp_or_asm = false; bool ensure_libc_on_non_freestanding = false; bool ensure_libcpp_on_non_freestanding = false; @@ -615,20 +615,22 @@ static int main0(int argc, char **argv) { } break; case Stage2ClangArgPositional: { - Buf *arg_buf = buf_create_from_str(it.only_arg); - if (buf_ends_with_str(arg_buf, ".c") || - buf_ends_with_str(arg_buf, ".C") || - buf_ends_with_str(arg_buf, ".cc") || - buf_ends_with_str(arg_buf, ".cpp") || - buf_ends_with_str(arg_buf, ".cxx") || - buf_ends_with_str(arg_buf, ".s") || - buf_ends_with_str(arg_buf, ".S")) - { - CFile *c_file = heap::c_allocator.create(); - c_file->source_path = it.only_arg; - c_source_files.append(c_file); - } else { - objects.append(it.only_arg); + FileExt file_ext = classify_file_ext(it.only_arg, strlen(it.only_arg)); + switch (file_ext) { + case FileExtAsm: + case FileExtC: + case FileExtCpp: + case FileExtLLVMIr: + case FileExtLLVMBitCode: + case FileExtHeader: { + CFile *c_file = heap::c_allocator.create(); + c_file->source_path = it.only_arg; + c_source_files.append(c_file); + break; + } + case FileExtUnknown: + objects.append(it.only_arg); + break; } break; } @@ -674,8 +676,12 @@ static int main0(int argc, char **argv) { } break; } - case Stage2ClangArgPreprocess: - only_preprocess = true; + case Stage2ClangArgPreprocessOrAsm: + // this handles both -E and -S + only_pp_or_asm = true; + for (size_t i = 0; i < it.other_args_len; i += 1) { + clang_argv.append(it.other_args_ptr[i]); + } break; case Stage2ClangArgOptimize: // alright what release mode do they want? @@ -799,7 +805,7 @@ static int main0(int argc, char **argv) { build_mode = BuildModeSafeRelease; } - if (only_preprocess) { + if (only_pp_or_asm) { cmd = CmdBuild; out_type = OutTypeObj; emit_bin = false; @@ -1597,7 +1603,7 @@ static int main0(int argc, char **argv) { #endif Buf *dest_path = buf_create_from_str(emit_bin_override_path); Buf *source_path; - if (only_preprocess) { + if (only_pp_or_asm) { source_path = buf_alloc(); Buf *pp_only_basename = buf_create_from_str( c_source_files.at(0)->preprocessor_only_basename); @@ -1611,7 +1617,7 @@ static int main0(int argc, char **argv) { buf_ptr(dest_path), err_str(err)); return main_exit(root_progress_node, EXIT_FAILURE); } - } else if (only_preprocess) { + } else if (only_pp_or_asm) { #if defined(ZIG_OS_WINDOWS) buf_replace(g->c_artifact_dir, '/', '\\'); #endif diff --git a/src/stage2.h b/src/stage2.h index 54355ea73..49e0dcc28 100644 --- a/src/stage2.h +++ b/src/stage2.h @@ -339,7 +339,7 @@ enum Stage2ClangArg { Stage2ClangArgShared, Stage2ClangArgRDynamic, Stage2ClangArgWL, - Stage2ClangArgPreprocess, + Stage2ClangArgPreprocessOrAsm, Stage2ClangArgOptimize, Stage2ClangArgDebug, Stage2ClangArgSanitize, diff --git a/src/util.hpp b/src/util.hpp index a11960624..bd1a5b1e4 100644 --- a/src/util.hpp +++ b/src/util.hpp @@ -100,6 +100,15 @@ static inline bool is_power_of_2(uint64_t x) { return x != 0 && ((x & (~x + 1)) == x); } +static inline bool mem_ends_with_mem(const char *mem, size_t mem_len, const char *end, size_t end_len) { + if (mem_len < end_len) return false; + return memcmp(mem + mem_len - end_len, end, end_len) == 0; +} + +static inline bool mem_ends_with_str(const char *mem, size_t mem_len, const char *str) { + return mem_ends_with_mem(mem, mem_len, str, strlen(str)); +} + static inline uint64_t round_to_next_power_of_2(uint64_t x) { --x; x |= x >> 1; diff --git a/tools/update_clang_options.zig b/tools/update_clang_options.zig index f5b483e66..d2ad8cad3 100644 --- a/tools/update_clang_options.zig +++ b/tools/update_clang_options.zig @@ -96,19 +96,19 @@ const known_options = [_]KnownOpt{ }, .{ .name = "E", - .ident = "preprocess", + .ident = "pp_or_asm", }, .{ .name = "preprocess", - .ident = "preprocess", + .ident = "pp_or_asm", }, .{ .name = "S", - .ident = "driver_punt", + .ident = "pp_or_asm", }, .{ .name = "assemble", - .ident = "driver_punt", + .ident = "pp_or_asm", }, .{ .name = "O1",