From 976080462cf62f6f112d38176b99e5bb8a57bf37 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 21 Apr 2019 17:24:58 -0400 Subject: translate-c: a little closer to self-hosted implementation --- src/ir.cpp | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) (limited to 'src/ir.cpp') diff --git a/src/ir.cpp b/src/ir.cpp index 62eadeb43f..105dd0c3d6 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -10350,7 +10350,7 @@ ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *nod if (codegen->verbose_ir) { fprintf(stderr, "\nSource: "); - ast_render(codegen, stderr, node, 4); + ast_render(stderr, node, 4); fprintf(stderr, "\n{ // (IR)\n"); ir_print(codegen, stderr, ir_executable, 2); fprintf(stderr, "}\n"); @@ -19092,11 +19092,23 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct fprintf(stderr, "@cImport source: %s\n", buf_ptr(&tmp_c_file_path)); } - ZigList errors = {0}; - Buf *tmp_dep_file = buf_sprintf("%s.d", buf_ptr(&tmp_c_file_path)); + + ZigList clang_argv = {0}; + + add_cc_args(ira->codegen, clang_argv, buf_ptr(tmp_dep_file), true); + + clang_argv.append("-c"); + clang_argv.append(buf_ptr(&tmp_c_file_path)); + + clang_argv.append(nullptr); // to make the [start...end] argument work + + ZigList errors = {0}; AstNode *root_node; - if ((err = parse_h_file(&root_node, &errors, buf_ptr(&tmp_c_file_path), ira->codegen, tmp_dep_file))) { + + if ((err = parse_h_file(ira->codegen, &root_node, &clang_argv.at(0), &clang_argv.last(), + Stage2TranslateModeImport, &errors))) + { if (err != ErrorCCompileErrors) { ir_add_error_node(ira, node, buf_sprintf("C import failed: %s", err_str(err))); return ira->codegen->invalid_instruction; @@ -19139,7 +19151,7 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct buf_sprintf("C import failed: unable to open output file: %s", strerror(errno))); return ira->codegen->invalid_instruction; } - ast_render(ira->codegen, out_file, root_node, 4); + ast_render(out_file, root_node, 4); if (fclose(out_file) != 0) { ir_add_error_node(ira, node, buf_sprintf("C import failed: unable to write to output file: %s", strerror(errno))); -- cgit v1.2.3 From 712274997e80a93bdfe204f2238c4cfaac72a5b8 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 21 Apr 2019 19:37:39 -0400 Subject: translate-c: unify API for self-hosted and C++ translate-c See #1964 --- src-self-hosted/clang.zig | 17 ++++++ src-self-hosted/main.zig | 18 ++++++- src-self-hosted/stage1.zig | 35 ++++++------- src-self-hosted/translate_c.zig | 13 ++++- src/codegen.cpp | 49 +++++++++++------- src/ir.cpp | 19 ++++--- src/translate_c.cpp | 86 ++++-------------------------- src/translate_c.hpp | 6 ++- src/userland.cpp | 9 +++- src/userland.h | 46 +++++++++++++---- src/zig_clang.cpp | 112 ++++++++++++++++++++++++++++++++++++++++ src/zig_clang.h | 14 ++--- 12 files changed, 281 insertions(+), 143 deletions(-) (limited to 'src/ir.cpp') diff --git a/src-self-hosted/clang.zig b/src-self-hosted/clang.zig index 6f7c7eb853..a9cf06f8a5 100644 --- a/src-self-hosted/clang.zig +++ b/src-self-hosted/clang.zig @@ -862,6 +862,7 @@ pub extern fn ZigClangAPSInt_free(self: ?*const struct_ZigClangAPSInt) void; pub extern fn ZigClangAPSInt_getRawData(self: ?*const struct_ZigClangAPSInt) [*c]const u64; pub extern fn ZigClangAPSInt_getNumWords(self: ?*const struct_ZigClangAPSInt) c_uint; pub extern fn ZigClangAPValueLValueBase_dyn_cast_Expr(self: struct_ZigClangAPValueLValueBase) ?*const struct_ZigClangExpr; +pub extern fn ZigClangASTUnit_delete(arg0: ?*struct_ZigClangASTUnit) void; pub const ZigClangSourceLocation = struct_ZigClangSourceLocation; pub const ZigClangQualType = struct_ZigClangQualType; pub const ZigClangAPValueLValueBase = struct_ZigClangAPValueLValueBase; @@ -942,3 +943,19 @@ pub const ZigClangTypeClass = enum_ZigClangTypeClass; pub const ZigClangStmtClass = enum_ZigClangStmtClass; pub const ZigClangCK = enum_ZigClangCK; pub const ZigClangAPValueKind = enum_ZigClangAPValueKind; + +pub const Stage2ErrorMsg = extern struct { + filename_ptr: ?[*]const u8, + filename_len: usize, + msg_ptr: [*]const u8, + msg_len: usize, + // valid until the ASTUnit is freed + source: ?[*]const u8, + // 0 based + line: c_uint, + // 0 based + column: c_uint, + // byte offset into source + offset: c_uint, +}; +pub extern fn ZigClangErrorMsg_delete(ptr: [*c]Stage2ErrorMsg, len: usize) void; diff --git a/src-self-hosted/main.zig b/src-self-hosted/main.zig index 361afc80e3..759a84cb34 100644 --- a/src-self-hosted/main.zig +++ b/src-self-hosted/main.zig @@ -858,7 +858,23 @@ fn cmdHelp(allocator: *Allocator, args: []const []const u8) !void { try stdout.write(usage); } -const info_zen = @import("stage1.zig").info_zen; +pub const info_zen = + \\ + \\ * Communicate intent precisely. + \\ * Edge cases matter. + \\ * Favor reading code over writing code. + \\ * Only one obvious way to do things. + \\ * Runtime crashes are better than bugs. + \\ * Compile errors are better than runtime crashes. + \\ * Incremental improvements. + \\ * Avoid local maximums. + \\ * Reduce the amount one must remember. + \\ * Minimize energy spent on coding style. + \\ * Together we serve end users. + \\ + \\ +; + fn cmdZen(allocator: *Allocator, args: []const []const u8) !void { try stdout.write(info_zen); } diff --git a/src-self-hosted/stage1.zig b/src-self-hosted/stage1.zig index cf5f06c285..53bc1eeb69 100644 --- a/src-self-hosted/stage1.zig +++ b/src-self-hosted/stage1.zig @@ -3,37 +3,25 @@ const std = @import("std"); -pub const info_zen = - \\ - \\ * Communicate intent precisely. - \\ * Edge cases matter. - \\ * Favor reading code over writing code. - \\ * Only one obvious way to do things. - \\ * Runtime crashes are better than bugs. - \\ * Compile errors are better than runtime crashes. - \\ * Incremental improvements. - \\ * Avoid local maximums. - \\ * Reduce the amount one must remember. - \\ * Minimize energy spent on coding style. - \\ * Together we serve end users. - \\ - \\ -; - +// ABI warning export fn stage2_zen(ptr: *[*]const u8, len: *usize) void { + const info_zen = @import("main.zig").info_zen; ptr.* = &info_zen; len.* = info_zen.len; } +// ABI warning export fn stage2_panic(ptr: [*]const u8, len: usize) void { @panic(ptr[0..len]); } +// ABI warning const TranslateMode = extern enum { import, translate, }; +// ABI warning const Error = extern enum { None, OutOfMemory, @@ -84,24 +72,33 @@ const Error = extern enum { const FILE = std.c.FILE; const ast = std.zig.ast; +const translate_c = @import("translate_c.zig"); /// Args should have a null terminating last arg. export fn stage2_translate_c( out_ast: **ast.Tree, + out_errors_ptr: *[*]translate_c.ClangErrMsg, + out_errors_len: *usize, args_begin: [*]?[*]const u8, args_end: [*]?[*]const u8, mode: TranslateMode, + resources_path: [*]const u8, ) Error { - const translate_c = @import("translate_c.zig"); + var errors: []translate_c.ClangErrMsg = undefined; out_ast.* = translate_c.translate(args_begin, args_end, switch (mode) { .import => translate_c.Mode.import, .translate => translate_c.Mode.translate, - }) catch |err| switch (err) { + }, &errors) catch |err| switch (err) { error.Unimplemented => return Error.Unimplemented, }; + return Error.None; } +export fn stage2_free_clang_errors(errors_ptr: [*]translate_c.ClangErrMsg, errors_len: usize) void { + translate_c.freeErrors(errors_ptr[0..errors_len]); +} + export fn stage2_render_ast(tree: *ast.Tree, output_file: *FILE) Error { const c_out_stream = &std.io.COutStream.init(output_file).stream; _ = std.zig.render(std.heap.c_allocator, c_out_stream, tree) catch |e| switch (e) { diff --git a/src-self-hosted/translate_c.zig b/src-self-hosted/translate_c.zig index c2d943b1ff..b2dcfffeb3 100644 --- a/src-self-hosted/translate_c.zig +++ b/src-self-hosted/translate_c.zig @@ -10,6 +10,17 @@ pub const Mode = enum { translate, }; -pub fn translate(args_begin: [*]?[*]const u8, args_end: [*]?[*]const u8, mode: Mode) !*ast.Tree { +pub const ClangErrMsg = Stage2ErrorMsg; + +pub fn translate( + args_begin: [*]?[*]const u8, + args_end: [*]?[*]const u8, + mode: Mode, + errors: *[]ClangErrMsg, +) !*ast.Tree { return error.Unimplemented; } + +pub fn freeErrors(errors: []ClangErrMsg) void { + ZigClangErrorMsg_delete(errors.ptr, errors.len); +} diff --git a/src/codegen.cpp b/src/codegen.cpp index b4ea0a9a96..27e2195a3c 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -8298,31 +8298,42 @@ void codegen_translate_c(CodeGen *g, Buf *full_path, FILE *out_file, bool use_us clang_argv.append(nullptr); // to make the [start...end] argument work + const char *resources_path = buf_ptr(g->zig_c_headers_dir); + Stage2ErrorMsg *errors_ptr; + size_t errors_len; + Stage2Ast *ast; + AstNode *root_node; + if (use_userland_implementation) { - Stage2Ast *ast; - if ((err = stage2_translate_c(&ast, &clang_argv.at(0), &clang_argv.last(), trans_mode))) { - zig_panic("TODO"); - } - stage2_render_ast(ast, out_file); + err = stage2_translate_c(&ast, &errors_ptr, &errors_len, + &clang_argv.at(0), &clang_argv.last(), trans_mode, resources_path); } else { - ZigList errors = {0}; - AstNode *root_node; - - err = parse_h_file(g, &root_node, &clang_argv.at(0), &clang_argv.last(), trans_mode, &errors); + err = parse_h_file(g, &root_node, &errors_ptr, &errors_len, &clang_argv.at(0), &clang_argv.last(), + trans_mode, resources_path); + } - if (err == ErrorCCompileErrors && errors.length > 0) { - for (size_t i = 0; i < errors.length; i += 1) { - ErrorMsg *err_msg = errors.at(i); - print_err_msg(err_msg, g->err_color); - } - exit(1); + if (err == ErrorCCompileErrors && errors_len > 0) { + for (size_t i = 0; i < errors_len; i += 1) { + Stage2ErrorMsg *clang_err = &errors_ptr[i]; + ErrorMsg *err_msg = err_msg_create_with_offset( + clang_err->filename_ptr ? + buf_create_from_mem(clang_err->filename_ptr, clang_err->filename_len) : buf_alloc(), + clang_err->line, clang_err->column, clang_err->offset, clang_err->source, + buf_create_from_mem(clang_err->msg_ptr, clang_err->msg_len)); + print_err_msg(err_msg, g->err_color); } + exit(1); + } - if (err) { - fprintf(stderr, "unable to parse C file: %s\n", err_str(err)); - exit(1); - } + if (err) { + fprintf(stderr, "unable to parse C file: %s\n", err_str(err)); + exit(1); + } + + if (use_userland_implementation) { + stage2_render_ast(ast, out_file); + } else { ast_render(out_file, root_node, 4); } } diff --git a/src/ir.cpp b/src/ir.cpp index 105dd0c3d6..3f74741995 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -19103,25 +19103,32 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct clang_argv.append(nullptr); // to make the [start...end] argument work - ZigList errors = {0}; AstNode *root_node; + Stage2ErrorMsg *errors_ptr; + size_t errors_len; - if ((err = parse_h_file(ira->codegen, &root_node, &clang_argv.at(0), &clang_argv.last(), - Stage2TranslateModeImport, &errors))) + const char *resources_path = buf_ptr(ira->codegen->zig_c_headers_dir); + + if ((err = parse_h_file(ira->codegen, &root_node, &errors_ptr, &errors_len, + &clang_argv.at(0), &clang_argv.last(), Stage2TranslateModeImport, resources_path))) { if (err != ErrorCCompileErrors) { ir_add_error_node(ira, node, buf_sprintf("C import failed: %s", err_str(err))); return ira->codegen->invalid_instruction; } - assert(errors.length > 0); ErrorMsg *parent_err_msg = ir_add_error_node(ira, node, buf_sprintf("C import failed")); if (ira->codegen->libc_link_lib == nullptr) { add_error_note(ira->codegen, parent_err_msg, node, buf_sprintf("libc headers not available; compilation does not link against libc")); } - for (size_t i = 0; i < errors.length; i += 1) { - ErrorMsg *err_msg = errors.at(i); + for (size_t i = 0; i < errors_len; i += 1) { + Stage2ErrorMsg *clang_err = &errors_ptr[i]; + ErrorMsg *err_msg = err_msg_create_with_offset( + clang_err->filename_ptr ? + buf_create_from_mem(clang_err->filename_ptr, clang_err->filename_len) : buf_alloc(), + clang_err->line, clang_err->column, clang_err->offset, clang_err->source, + buf_create_from_mem(clang_err->msg_ptr, clang_err->msg_len)); err_msg_add_note(parent_err_msg, err_msg); } diff --git a/src/translate_c.cpp b/src/translate_c.cpp index d19083ce73..1c8d8e51b3 100644 --- a/src/translate_c.cpp +++ b/src/translate_c.cpp @@ -76,10 +76,9 @@ struct TransScopeWhile { }; struct Context { - ZigList *errors; + AstNode *root; VisibMod visib_mod; bool want_export; - AstNode *root; HashMap decl_table; HashMap macro_table; HashMap global_table; @@ -5018,13 +5017,14 @@ static void process_preprocessor_entities(Context *c, ZigClangASTUnit *zunit) { } } -Error parse_h_file(CodeGen *codegen, AstNode **out_root_node, const char **args_begin, const char **args_end, - Stage2TranslateMode mode, ZigList *errors) +Error parse_h_file(CodeGen *codegen, AstNode **out_root_node, + Stage2ErrorMsg **errors_ptr, size_t *errors_len, + const char **args_begin, const char **args_end, + Stage2TranslateMode mode, const char *resources_path) { Context context = {0}; Context *c = &context; c->warnings_on = codegen->verbose_cimport; - c->errors = errors; if (mode == Stage2TranslateModeImport) { c->visib_mod = VisibModPub; c->want_export = false; @@ -5039,78 +5039,10 @@ Error parse_h_file(CodeGen *codegen, AstNode **out_root_node, const char **args_ c->codegen = codegen; c->global_scope = trans_scope_root_create(c); - - clang::IntrusiveRefCntPtr diags(clang::CompilerInstance::createDiagnostics(new clang::DiagnosticOptions)); - - std::shared_ptr pch_container_ops = std::make_shared(); - - bool only_local_decls = true; - bool capture_diagnostics = true; - bool user_files_are_volatile = true; - bool allow_pch_with_compiler_errors = false; - bool single_file_parse = false; - bool for_serialization = false; - const char *resources_path = buf_ptr(codegen->zig_c_headers_dir); - std::unique_ptr err_unit; - ZigClangASTUnit *ast_unit = reinterpret_cast(clang::ASTUnit::LoadFromCommandLine( - args_begin, args_end, - pch_container_ops, diags, resources_path, - only_local_decls, capture_diagnostics, clang::None, true, 0, clang::TU_Complete, - false, false, allow_pch_with_compiler_errors, clang::SkipFunctionBodiesScope::None, - single_file_parse, user_files_are_volatile, for_serialization, clang::None, &err_unit, - nullptr)); - - // Early failures in LoadFromCommandLine may return with ErrUnit unset. - if (!ast_unit && !err_unit) { - return ErrorFileSystem; - } - - if (diags->getClient()->getNumErrors() > 0) { - if (ast_unit) { - err_unit = std::unique_ptr(reinterpret_cast(ast_unit)); - } - - for (clang::ASTUnit::stored_diag_iterator it = err_unit->stored_diag_begin(), - it_end = err_unit->stored_diag_end(); - it != it_end; ++it) - { - switch (it->getLevel()) { - case clang::DiagnosticsEngine::Ignored: - case clang::DiagnosticsEngine::Note: - case clang::DiagnosticsEngine::Remark: - case clang::DiagnosticsEngine::Warning: - continue; - case clang::DiagnosticsEngine::Error: - case clang::DiagnosticsEngine::Fatal: - break; - } - llvm::StringRef msg_str_ref = it->getMessage(); - Buf *msg = string_ref_to_buf(msg_str_ref); - clang::FullSourceLoc fsl = it->getLocation(); - if (fsl.hasManager()) { - clang::FileID file_id = fsl.getFileID(); - clang::StringRef filename = fsl.getManager().getFilename(fsl); - unsigned line = fsl.getSpellingLineNumber() - 1; - unsigned column = fsl.getSpellingColumnNumber() - 1; - unsigned offset = fsl.getManager().getFileOffset(fsl); - const char *source = (const char *)fsl.getManager().getBufferData(file_id).bytes_begin(); - Buf *path; - if (filename.empty()) { - path = buf_alloc(); - } else { - path = string_ref_to_buf(filename); - } - - ErrorMsg *err_msg = err_msg_create_with_offset(path, line, column, offset, source, msg); - - c->errors->append(err_msg); - } else { - // NOTE the only known way this gets triggered right now is if you have a lot of errors - // clang emits "too many errors emitted, stopping now" - fprintf(stderr, "unexpected error from clang: %s\n", buf_ptr(msg)); - } - } - + ZigClangASTUnit *ast_unit = ZigClangLoadFromCommandLine(args_begin, args_end, errors_ptr, errors_len, + resources_path); + if (ast_unit == nullptr) { + if (*errors_len == 0) return ErrorNoMem; return ErrorCCompileErrors; } diff --git a/src/translate_c.hpp b/src/translate_c.hpp index b6e4b6bcbb..4eac26ddb5 100644 --- a/src/translate_c.hpp +++ b/src/translate_c.hpp @@ -11,7 +11,9 @@ #include "all_types.hpp" -Error parse_h_file(CodeGen *codegen, AstNode **out_root_node, const char **args_begin, const char **args_end, - Stage2TranslateMode mode, ZigList *errors); +Error parse_h_file(CodeGen *codegen, AstNode **out_root_node, + Stage2ErrorMsg **errors_ptr, size_t *errors_len, + const char **args_begin, const char **args_end, + Stage2TranslateMode mode, const char *resources_path); #endif diff --git a/src/userland.cpp b/src/userland.cpp index 9935d5c04a..fad1450f0d 100644 --- a/src/userland.cpp +++ b/src/userland.cpp @@ -8,12 +8,19 @@ #include Error stage2_translate_c(struct Stage2Ast **out_ast, - const char **args_begin, const char **args_end, enum Stage2TranslateMode mode) + struct Stage2ErrorMsg **out_errors_ptr, size_t *out_errors_len, + const char **args_begin, const char **args_end, enum Stage2TranslateMode mode, + const char *resources_path) { const char *msg = "stage0 called stage2_translate_c"; stage2_panic(msg, strlen(msg)); } +void stage2_free_clang_errors(struct Stage2ErrorMsg *ptr, size_t len) { + const char *msg = "stage0 called stage2_free_clang_errors"; + stage2_panic(msg, strlen(msg)); +} + void stage2_zen(const char **ptr, size_t *len) { const char *msg = "stage0 called stage2_zen"; stage2_panic(msg, strlen(msg)); diff --git a/src/userland.h b/src/userland.h index 35fd46942b..ba797d8b25 100644 --- a/src/userland.h +++ b/src/userland.h @@ -12,20 +12,21 @@ #include #ifdef __cplusplus -#define ZIG_USERLAND_EXTERN_C extern "C" +#define ZIG_EXTERN_C extern "C" #else -#define ZIG_USERLAND_EXTERN_C +#define ZIG_EXTERN_C #endif #if defined(_MSC_VER) -#define ZIG_USERLAND_ATTRIBUTE_NORETURN __declspec(noreturn) +#define ZIG_ATTRIBUTE_NORETURN __declspec(noreturn) #else -#define ZIG_USERLAND_ATTRIBUTE_NORETURN __attribute__((noreturn)) +#define ZIG_ATTRIBUTE_NORETURN __attribute__((noreturn)) #endif -// The types and declarations in this file must match both those in userland.cpp and -// src-self-hosted/stage1.zig. +// ABI warning: the types and declarations in this file must match both those in +// userland.cpp and src-self-hosted/stage1.zig. +// ABI warning enum Error { ErrorNone, ErrorNoMem, @@ -74,20 +75,43 @@ enum Error { ErrorNoSpaceLeft, }; +// ABI warning enum Stage2TranslateMode { Stage2TranslateModeImport, Stage2TranslateModeTranslate, }; +// ABI warning +struct Stage2ErrorMsg { + const char *filename_ptr; // can be null + size_t filename_len; + const char *msg_ptr; + size_t msg_len; + const char *source; // valid until the ASTUnit is freed. can be null + unsigned line; // 0 based + unsigned column; // 0 based + unsigned offset; // byte offset into source +}; + +// ABI warning struct Stage2Ast; -ZIG_USERLAND_EXTERN_C Error stage2_translate_c(struct Stage2Ast **out_ast, - const char **args_begin, const char **args_end, enum Stage2TranslateMode mode); +// ABI warning +ZIG_EXTERN_C enum Error stage2_translate_c(struct Stage2Ast **out_ast, + struct Stage2ErrorMsg **out_errors_ptr, size_t *out_errors_len, + const char **args_begin, const char **args_end, enum Stage2TranslateMode mode, + const char *resources_path); + +// ABI warning +ZIG_EXTERN_C void stage2_free_clang_errors(struct Stage2ErrorMsg *ptr, size_t len); -ZIG_USERLAND_EXTERN_C void stage2_render_ast(struct Stage2Ast *ast, FILE *output_file); +// ABI warning +ZIG_EXTERN_C void stage2_render_ast(struct Stage2Ast *ast, FILE *output_file); -ZIG_USERLAND_EXTERN_C void stage2_zen(const char **ptr, size_t *len); +// ABI warning +ZIG_EXTERN_C void stage2_zen(const char **ptr, size_t *len); -ZIG_USERLAND_EXTERN_C ZIG_USERLAND_ATTRIBUTE_NORETURN void stage2_panic(const char *ptr, size_t len); +// ABI warning +ZIG_EXTERN_C ZIG_ATTRIBUTE_NORETURN void stage2_panic(const char *ptr, size_t len); #endif diff --git a/src/zig_clang.cpp b/src/zig_clang.cpp index 6142c808ad..cc79941190 100644 --- a/src/zig_clang.cpp +++ b/src/zig_clang.cpp @@ -1147,3 +1147,115 @@ ZigClangAPValueLValueBase ZigClangAPValue_getLValueBase(const ZigClangAPValue *s clang::APValue::LValueBase lval_base = casted->getLValueBase(); return bitcast(lval_base); } + +ZigClangASTUnit *ZigClangLoadFromCommandLine(const char **args_begin, const char **args_end, + struct Stage2ErrorMsg **errors_ptr, size_t *errors_len, const char *resources_path) +{ + clang::IntrusiveRefCntPtr diags(clang::CompilerInstance::createDiagnostics(new clang::DiagnosticOptions)); + + std::shared_ptr pch_container_ops = std::make_shared(); + + bool only_local_decls = true; + bool capture_diagnostics = true; + bool user_files_are_volatile = true; + bool allow_pch_with_compiler_errors = false; + bool single_file_parse = false; + bool for_serialization = false; + std::unique_ptr *err_unit = new std::unique_ptr(); + clang::ASTUnit *ast_unit = clang::ASTUnit::LoadFromCommandLine( + args_begin, args_end, + pch_container_ops, diags, resources_path, + only_local_decls, capture_diagnostics, clang::None, true, 0, clang::TU_Complete, + false, false, allow_pch_with_compiler_errors, clang::SkipFunctionBodiesScope::None, + single_file_parse, user_files_are_volatile, for_serialization, clang::None, err_unit, + nullptr); + + // Early failures in LoadFromCommandLine may return with ErrUnit unset. + if (!ast_unit && !err_unit) { + return nullptr; + } + + if (diags->getClient()->getNumErrors() > 0) { + if (ast_unit) { + *err_unit = std::unique_ptr(ast_unit); + } + + size_t cap = 4; + *errors_len = 0; + *errors_ptr = reinterpret_cast(malloc(cap * sizeof(Stage2ErrorMsg))); + if (*errors_ptr == nullptr) { + return nullptr; + } + + for (clang::ASTUnit::stored_diag_iterator it = (*err_unit)->stored_diag_begin(), + it_end = (*err_unit)->stored_diag_end(); + it != it_end; ++it) + { + switch (it->getLevel()) { + case clang::DiagnosticsEngine::Ignored: + case clang::DiagnosticsEngine::Note: + case clang::DiagnosticsEngine::Remark: + case clang::DiagnosticsEngine::Warning: + continue; + case clang::DiagnosticsEngine::Error: + case clang::DiagnosticsEngine::Fatal: + break; + } + llvm::StringRef msg_str_ref = it->getMessage(); + if (*errors_len >= cap) { + cap *= 2; + Stage2ErrorMsg *new_errors = reinterpret_cast( + realloc(*errors_ptr, cap * sizeof(Stage2ErrorMsg))); + if (new_errors == nullptr) { + free(*errors_ptr); + *errors_ptr = nullptr; + *errors_len = 0; + return nullptr; + } + *errors_ptr = new_errors; + } + Stage2ErrorMsg *msg = *errors_ptr + *errors_len; + *errors_len += 1; + msg->msg_ptr = (const char *)msg_str_ref.bytes_begin(); + msg->msg_len = msg_str_ref.size(); + + clang::FullSourceLoc fsl = it->getLocation(); + if (fsl.hasManager()) { + clang::FileID file_id = fsl.getFileID(); + clang::StringRef filename = fsl.getManager().getFilename(fsl); + if (filename.empty()) { + msg->filename_ptr = nullptr; + } else { + msg->filename_ptr = (const char *)filename.bytes_begin(); + msg->filename_len = filename.size(); + } + msg->source = (const char *)fsl.getManager().getBufferData(file_id).bytes_begin(); + msg->line = fsl.getSpellingLineNumber() - 1; + msg->column = fsl.getSpellingColumnNumber() - 1; + msg->offset = fsl.getManager().getFileOffset(fsl); + } else { + // The only known way this gets triggered right now is if you have a lot of errors + // clang emits "too many errors emitted, stopping now" + msg->filename_ptr = nullptr; + msg->source = nullptr; + } + } + + if (*errors_len == 0) { + free(*errors_ptr); + *errors_ptr = nullptr; + } + + return nullptr; + } + + return reinterpret_cast(ast_unit); +} + +void ZigClangErrorMsg_delete(Stage2ErrorMsg *ptr, size_t len) { + free(ptr); +} + +void ZigClangASTUnit_delete(struct ZigClangASTUnit *self) { + delete reinterpret_cast(self); +} diff --git a/src/zig_clang.h b/src/zig_clang.h index 148ee34f51..f237449527 100644 --- a/src/zig_clang.h +++ b/src/zig_clang.h @@ -8,15 +8,10 @@ #ifndef ZIG_ZIG_CLANG_H #define ZIG_ZIG_CLANG_H +#include "userland.h" #include #include -#ifdef __cplusplus -#define ZIG_EXTERN_C extern "C" -#else -#define ZIG_EXTERN_C -#endif - // ATTENTION: If you modify this file, be sure to update the corresponding // extern function declarations in the self-hosted compiler file // src-self-hosted/clang.zig. @@ -500,6 +495,13 @@ ZIG_EXTERN_C const char* ZigClangSourceManager_getCharacterData(const struct Zig ZIG_EXTERN_C struct ZigClangQualType ZigClangASTContext_getPointerType(const struct ZigClangASTContext*, struct ZigClangQualType T); + +// Can return null. +ZIG_EXTERN_C struct ZigClangASTUnit *ZigClangLoadFromCommandLine(const char **args_begin, const char **args_end, + struct Stage2ErrorMsg **errors_ptr, size_t *errors_len, const char *resources_path); +ZIG_EXTERN_C void ZigClangASTUnit_delete(struct ZigClangASTUnit *); +ZIG_EXTERN_C void ZigClangErrorMsg_delete(struct Stage2ErrorMsg *ptr, size_t len); + ZIG_EXTERN_C struct ZigClangASTContext *ZigClangASTUnit_getASTContext(struct ZigClangASTUnit *); ZIG_EXTERN_C struct ZigClangSourceManager *ZigClangASTUnit_getSourceManager(struct ZigClangASTUnit *); ZIG_EXTERN_C bool ZigClangASTUnit_visitLocalTopLevelDecls(struct ZigClangASTUnit *, void *context, -- cgit v1.2.3 From e1bf74fca3de7943b8f7c15be4da3dbc8e3da17e Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 21 Apr 2019 20:19:48 -0400 Subject: translate-c: put -x c back in there, it's necessary --- src/codegen.cpp | 21 +++++++++++++-------- src/ir.cpp | 9 ++++++++- src/translate_c.cpp | 2 ++ 3 files changed, 23 insertions(+), 9 deletions(-) (limited to 'src/ir.cpp') diff --git a/src/codegen.cpp b/src/codegen.cpp index 27e2195a3c..8d39c60ef7 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -8155,6 +8155,11 @@ 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) { + if (translate_c) { + args.append("-x"); + args.append("c"); + } + if (out_dep_path != nullptr) { args.append("-MD"); args.append("-MV"); @@ -8166,13 +8171,6 @@ void add_cc_args(CodeGen *g, ZigList &args, const char *out_dep_pa args.append("-fno-spell-checking"); if (translate_c) { - // TODO these args shouldn't be special from the non-translate-c args, probably. - args.append("-nobuiltininc"); - args.append("-nostdinc++"); - if (g->libc_link_lib == nullptr) { - args.append("-nolibc"); - } - // this gives us access to preprocessing entities, presumably at // the cost of performance args.append("-Xclang"); @@ -8293,9 +8291,16 @@ void codegen_translate_c(CodeGen *g, Buf *full_path, FILE *out_file, bool use_us ZigList clang_argv = {0}; add_cc_args(g, clang_argv, nullptr, true); - clang_argv.append("-c"); clang_argv.append(buf_ptr(full_path)); + if (g->verbose_cc) { + fprintf(stderr, "clang"); + for (size_t i = 0; i < clang_argv.length; i += 1) { + fprintf(stderr, " %s", clang_argv.at(i)); + } + fprintf(stderr, "\n"); + } + clang_argv.append(nullptr); // to make the [start...end] argument work const char *resources_path = buf_ptr(g->zig_c_headers_dir); diff --git a/src/ir.cpp b/src/ir.cpp index 3f74741995..a2bd72b197 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -19098,9 +19098,16 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct add_cc_args(ira->codegen, clang_argv, buf_ptr(tmp_dep_file), true); - clang_argv.append("-c"); clang_argv.append(buf_ptr(&tmp_c_file_path)); + if (ira->codegen->verbose_cc) { + fprintf(stderr, "clang"); + for (size_t i = 0; i < clang_argv.length; i += 1) { + fprintf(stderr, " %s", clang_argv.at(i)); + } + fprintf(stderr, "\n"); + } + clang_argv.append(nullptr); // to make the [start...end] argument work AstNode *root_node; diff --git a/src/translate_c.cpp b/src/translate_c.cpp index 1c8d8e51b3..f8e57098a6 100644 --- a/src/translate_c.cpp +++ b/src/translate_c.cpp @@ -5060,5 +5060,7 @@ Error parse_h_file(CodeGen *codegen, AstNode **out_root_node, *out_root_node = c->root; + ZigClangASTUnit_delete(ast_unit); + return ErrorNone; } -- cgit v1.2.3