| author | |
| committer | |
| log | 712274997e80a93bdfe204f2238c4cfaac72a5b8 |
| tree | 1931c87f8222bb961e6a530e277f7a30ef56c2c8 |
| parent | 976080462cf62f6f112d38176b99e5bb8a57bf37 |
| signature | Commit is signed but in an unrecognized format. |
See #196412 files changed, 281 insertions(+), 143 deletions(-)
src-self-hosted/clang.zig+17| ... | ... | @@ -862,6 +862,7 @@ pub extern fn ZigClangAPSInt_free(self: ?*const struct_ZigClangAPSInt) void; |
| 862 | 862 | pub extern fn ZigClangAPSInt_getRawData(self: ?*const struct_ZigClangAPSInt) [*c]const u64; |
| 863 | 863 | pub extern fn ZigClangAPSInt_getNumWords(self: ?*const struct_ZigClangAPSInt) c_uint; |
| 864 | 864 | pub extern fn ZigClangAPValueLValueBase_dyn_cast_Expr(self: struct_ZigClangAPValueLValueBase) ?*const struct_ZigClangExpr; |
| 865 | pub extern fn ZigClangASTUnit_delete(arg0: ?*struct_ZigClangASTUnit) void; | |
| 865 | 866 | pub const ZigClangSourceLocation = struct_ZigClangSourceLocation; |
| 866 | 867 | pub const ZigClangQualType = struct_ZigClangQualType; |
| 867 | 868 | pub const ZigClangAPValueLValueBase = struct_ZigClangAPValueLValueBase; |
| ... | ... | @@ -942,3 +943,19 @@ pub const ZigClangTypeClass = enum_ZigClangTypeClass; |
| 942 | 943 | pub const ZigClangStmtClass = enum_ZigClangStmtClass; |
| 943 | 944 | pub const ZigClangCK = enum_ZigClangCK; |
| 944 | 945 | pub const ZigClangAPValueKind = enum_ZigClangAPValueKind; |
| 946 | ||
| 947 | pub const Stage2ErrorMsg = extern struct { | |
| 948 | filename_ptr: ?[*]const u8, | |
| 949 | filename_len: usize, | |
| 950 | msg_ptr: [*]const u8, | |
| 951 | msg_len: usize, | |
| 952 | // valid until the ASTUnit is freed | |
| 953 | source: ?[*]const u8, | |
| 954 | // 0 based | |
| 955 | line: c_uint, | |
| 956 | // 0 based | |
| 957 | column: c_uint, | |
| 958 | // byte offset into source | |
| 959 | offset: c_uint, | |
| 960 | }; | |
| 961 | pub extern fn ZigClangErrorMsg_delete(ptr: [*c]Stage2ErrorMsg, len: usize) void; |
src-self-hosted/main.zig+17-1| ... | ... | @@ -858,7 +858,23 @@ fn cmdHelp(allocator: *Allocator, args: []const []const u8) !void { |
| 858 | 858 | try stdout.write(usage); |
| 859 | 859 | } |
| 860 | 860 | |
| 861 | const info_zen = @import("stage1.zig").info_zen; | |
| 861 | pub const info_zen = | |
| 862 | \\ | |
| 863 | \\ * Communicate intent precisely. | |
| 864 | \\ * Edge cases matter. | |
| 865 | \\ * Favor reading code over writing code. | |
| 866 | \\ * Only one obvious way to do things. | |
| 867 | \\ * Runtime crashes are better than bugs. | |
| 868 | \\ * Compile errors are better than runtime crashes. | |
| 869 | \\ * Incremental improvements. | |
| 870 | \\ * Avoid local maximums. | |
| 871 | \\ * Reduce the amount one must remember. | |
| 872 | \\ * Minimize energy spent on coding style. | |
| 873 | \\ * Together we serve end users. | |
| 874 | \\ | |
| 875 | \\ | |
| 876 | ; | |
| 877 | ||
| 862 | 878 | fn cmdZen(allocator: *Allocator, args: []const []const u8) !void { |
| 863 | 879 | try stdout.write(info_zen); |
| 864 | 880 | } |
src-self-hosted/stage1.zig+16-19| ... | ... | @@ -3,37 +3,25 @@ |
| 3 | 3 | |
| 4 | 4 | const std = @import("std"); |
| 5 | 5 | |
| 6 | pub const info_zen = | |
| 7 | \\ | |
| 8 | \\ * Communicate intent precisely. | |
| 9 | \\ * Edge cases matter. | |
| 10 | \\ * Favor reading code over writing code. | |
| 11 | \\ * Only one obvious way to do things. | |
| 12 | \\ * Runtime crashes are better than bugs. | |
| 13 | \\ * Compile errors are better than runtime crashes. | |
| 14 | \\ * Incremental improvements. | |
| 15 | \\ * Avoid local maximums. | |
| 16 | \\ * Reduce the amount one must remember. | |
| 17 | \\ * Minimize energy spent on coding style. | |
| 18 | \\ * Together we serve end users. | |
| 19 | \\ | |
| 20 | \\ | |
| 21 | ; | |
| 22 | ||
| 6 | // ABI warning | |
| 23 | 7 | export fn stage2_zen(ptr: *[*]const u8, len: *usize) void { |
| 8 | const info_zen = @import("main.zig").info_zen; | |
| 24 | 9 | ptr.* = &info_zen; |
| 25 | 10 | len.* = info_zen.len; |
| 26 | 11 | } |
| 27 | 12 | |
| 13 | // ABI warning | |
| 28 | 14 | export fn stage2_panic(ptr: [*]const u8, len: usize) void { |
| 29 | 15 | @panic(ptr[0..len]); |
| 30 | 16 | } |
| 31 | 17 | |
| 18 | // ABI warning | |
| 32 | 19 | const TranslateMode = extern enum { |
| 33 | 20 | import, |
| 34 | 21 | translate, |
| 35 | 22 | }; |
| 36 | 23 | |
| 24 | // ABI warning | |
| 37 | 25 | const Error = extern enum { |
| 38 | 26 | None, |
| 39 | 27 | OutOfMemory, |
| ... | ... | @@ -84,24 +72,33 @@ const Error = extern enum { |
| 84 | 72 | |
| 85 | 73 | const FILE = std.c.FILE; |
| 86 | 74 | const ast = std.zig.ast; |
| 75 | const translate_c = @import("translate_c.zig"); | |
| 87 | 76 | |
| 88 | 77 | /// Args should have a null terminating last arg. |
| 89 | 78 | export fn stage2_translate_c( |
| 90 | 79 | out_ast: **ast.Tree, |
| 80 | out_errors_ptr: *[*]translate_c.ClangErrMsg, | |
| 81 | out_errors_len: *usize, | |
| 91 | 82 | args_begin: [*]?[*]const u8, |
| 92 | 83 | args_end: [*]?[*]const u8, |
| 93 | 84 | mode: TranslateMode, |
| 85 | resources_path: [*]const u8, | |
| 94 | 86 | ) Error { |
| 95 | const translate_c = @import("translate_c.zig"); | |
| 87 | var errors: []translate_c.ClangErrMsg = undefined; | |
| 96 | 88 | out_ast.* = translate_c.translate(args_begin, args_end, switch (mode) { |
| 97 | 89 | .import => translate_c.Mode.import, |
| 98 | 90 | .translate => translate_c.Mode.translate, |
| 99 | }) catch |err| switch (err) { | |
| 91 | }, &errors) catch |err| switch (err) { | |
| 100 | 92 | error.Unimplemented => return Error.Unimplemented, |
| 101 | 93 | }; |
| 94 | ||
| 102 | 95 | return Error.None; |
| 103 | 96 | } |
| 104 | 97 | |
| 98 | export fn stage2_free_clang_errors(errors_ptr: [*]translate_c.ClangErrMsg, errors_len: usize) void { | |
| 99 | translate_c.freeErrors(errors_ptr[0..errors_len]); | |
| 100 | } | |
| 101 | ||
| 105 | 102 | export fn stage2_render_ast(tree: *ast.Tree, output_file: *FILE) Error { |
| 106 | 103 | const c_out_stream = &std.io.COutStream.init(output_file).stream; |
| 107 | 104 | _ = std.zig.render(std.heap.c_allocator, c_out_stream, tree) catch |e| switch (e) { |
src-self-hosted/translate_c.zig+12-1| ... | ... | @@ -10,6 +10,17 @@ pub const Mode = enum { |
| 10 | 10 | translate, |
| 11 | 11 | }; |
| 12 | 12 | |
| 13 | pub fn translate(args_begin: [*]?[*]const u8, args_end: [*]?[*]const u8, mode: Mode) !*ast.Tree { | |
| 13 | pub const ClangErrMsg = Stage2ErrorMsg; | |
| 14 | ||
| 15 | pub fn translate( | |
| 16 | args_begin: [*]?[*]const u8, | |
| 17 | args_end: [*]?[*]const u8, | |
| 18 | mode: Mode, | |
| 19 | errors: *[]ClangErrMsg, | |
| 20 | ) !*ast.Tree { | |
| 14 | 21 | return error.Unimplemented; |
| 15 | 22 | } |
| 23 | ||
| 24 | pub fn freeErrors(errors: []ClangErrMsg) void { | |
| 25 | ZigClangErrorMsg_delete(errors.ptr, errors.len); | |
| 26 | } |
src/codegen.cpp+30-19| ... | ... | @@ -8298,31 +8298,42 @@ void codegen_translate_c(CodeGen *g, Buf *full_path, FILE *out_file, bool use_us |
| 8298 | 8298 | |
| 8299 | 8299 | clang_argv.append(nullptr); // to make the [start...end] argument work |
| 8300 | 8300 | |
| 8301 | const char *resources_path = buf_ptr(g->zig_c_headers_dir); | |
| 8302 | Stage2ErrorMsg *errors_ptr; | |
| 8303 | size_t errors_len; | |
| 8304 | Stage2Ast *ast; | |
| 8305 | AstNode *root_node; | |
| 8306 | ||
| 8301 | 8307 | if (use_userland_implementation) { |
| 8302 | Stage2Ast *ast; | |
| 8303 | if ((err = stage2_translate_c(&ast, &clang_argv.at(0), &clang_argv.last(), trans_mode))) { | |
| 8304 | zig_panic("TODO"); | |
| 8305 | } | |
| 8306 | stage2_render_ast(ast, out_file); | |
| 8308 | err = stage2_translate_c(&ast, &errors_ptr, &errors_len, | |
| 8309 | &clang_argv.at(0), &clang_argv.last(), trans_mode, resources_path); | |
| 8307 | 8310 | } else { |
| 8308 | ZigList<ErrorMsg *> errors = {0}; | |
| 8309 | AstNode *root_node; | |
| 8310 | ||
| 8311 | err = parse_h_file(g, &root_node, &clang_argv.at(0), &clang_argv.last(), trans_mode, &errors); | |
| 8311 | err = parse_h_file(g, &root_node, &errors_ptr, &errors_len, &clang_argv.at(0), &clang_argv.last(), | |
| 8312 | trans_mode, resources_path); | |
| 8313 | } | |
| 8312 | 8314 | |
| 8313 | if (err == ErrorCCompileErrors && errors.length > 0) { | |
| 8314 | for (size_t i = 0; i < errors.length; i += 1) { | |
| 8315 | ErrorMsg *err_msg = errors.at(i); | |
| 8316 | print_err_msg(err_msg, g->err_color); | |
| 8317 | } | |
| 8318 | exit(1); | |
| 8315 | if (err == ErrorCCompileErrors && errors_len > 0) { | |
| 8316 | for (size_t i = 0; i < errors_len; i += 1) { | |
| 8317 | Stage2ErrorMsg *clang_err = &errors_ptr[i]; | |
| 8318 | ErrorMsg *err_msg = err_msg_create_with_offset( | |
| 8319 | clang_err->filename_ptr ? | |
| 8320 | buf_create_from_mem(clang_err->filename_ptr, clang_err->filename_len) : buf_alloc(), | |
| 8321 | clang_err->line, clang_err->column, clang_err->offset, clang_err->source, | |
| 8322 | buf_create_from_mem(clang_err->msg_ptr, clang_err->msg_len)); | |
| 8323 | print_err_msg(err_msg, g->err_color); | |
| 8319 | 8324 | } |
| 8325 | exit(1); | |
| 8326 | } | |
| 8320 | 8327 | |
| 8321 | if (err) { | |
| 8322 | fprintf(stderr, "unable to parse C file: %s\n", err_str(err)); | |
| 8323 | exit(1); | |
| 8324 | } | |
| 8328 | if (err) { | |
| 8329 | fprintf(stderr, "unable to parse C file: %s\n", err_str(err)); | |
| 8330 | exit(1); | |
| 8331 | } | |
| 8325 | 8332 | |
| 8333 | ||
| 8334 | if (use_userland_implementation) { | |
| 8335 | stage2_render_ast(ast, out_file); | |
| 8336 | } else { | |
| 8326 | 8337 | ast_render(out_file, root_node, 4); |
| 8327 | 8338 | } |
| 8328 | 8339 | } |
src/ir.cpp+13-6| ... | ... | @@ -19103,25 +19103,32 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct |
| 19103 | 19103 | |
| 19104 | 19104 | clang_argv.append(nullptr); // to make the [start...end] argument work |
| 19105 | 19105 | |
| 19106 | ZigList<ErrorMsg *> errors = {0}; | |
| 19107 | 19106 | AstNode *root_node; |
| 19107 | Stage2ErrorMsg *errors_ptr; | |
| 19108 | size_t errors_len; | |
| 19108 | 19109 | |
| 19109 | if ((err = parse_h_file(ira->codegen, &root_node, &clang_argv.at(0), &clang_argv.last(), | |
| 19110 | Stage2TranslateModeImport, &errors))) | |
| 19110 | const char *resources_path = buf_ptr(ira->codegen->zig_c_headers_dir); | |
| 19111 | ||
| 19112 | if ((err = parse_h_file(ira->codegen, &root_node, &errors_ptr, &errors_len, | |
| 19113 | &clang_argv.at(0), &clang_argv.last(), Stage2TranslateModeImport, resources_path))) | |
| 19111 | 19114 | { |
| 19112 | 19115 | if (err != ErrorCCompileErrors) { |
| 19113 | 19116 | ir_add_error_node(ira, node, buf_sprintf("C import failed: %s", err_str(err))); |
| 19114 | 19117 | return ira->codegen->invalid_instruction; |
| 19115 | 19118 | } |
| 19116 | assert(errors.length > 0); | |
| 19117 | 19119 | |
| 19118 | 19120 | ErrorMsg *parent_err_msg = ir_add_error_node(ira, node, buf_sprintf("C import failed")); |
| 19119 | 19121 | if (ira->codegen->libc_link_lib == nullptr) { |
| 19120 | 19122 | add_error_note(ira->codegen, parent_err_msg, node, |
| 19121 | 19123 | buf_sprintf("libc headers not available; compilation does not link against libc")); |
| 19122 | 19124 | } |
| 19123 | for (size_t i = 0; i < errors.length; i += 1) { | |
| 19124 | ErrorMsg *err_msg = errors.at(i); | |
| 19125 | for (size_t i = 0; i < errors_len; i += 1) { | |
| 19126 | Stage2ErrorMsg *clang_err = &errors_ptr[i]; | |
| 19127 | ErrorMsg *err_msg = err_msg_create_with_offset( | |
| 19128 | clang_err->filename_ptr ? | |
| 19129 | buf_create_from_mem(clang_err->filename_ptr, clang_err->filename_len) : buf_alloc(), | |
| 19130 | clang_err->line, clang_err->column, clang_err->offset, clang_err->source, | |
| 19131 | buf_create_from_mem(clang_err->msg_ptr, clang_err->msg_len)); | |
| 19125 | 19132 | err_msg_add_note(parent_err_msg, err_msg); |
| 19126 | 19133 | } |
| 19127 | 19134 |
src/translate_c.cpp+9-77| ... | ... | @@ -76,10 +76,9 @@ struct TransScopeWhile { |
| 76 | 76 | }; |
| 77 | 77 | |
| 78 | 78 | struct Context { |
| 79 | ZigList<ErrorMsg *> *errors; | |
| 79 | AstNode *root; | |
| 80 | 80 | VisibMod visib_mod; |
| 81 | 81 | bool want_export; |
| 82 | AstNode *root; | |
| 83 | 82 | HashMap<const void *, AstNode *, ptr_hash, ptr_eq> decl_table; |
| 84 | 83 | HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> macro_table; |
| 85 | 84 | HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> global_table; |
| ... | ... | @@ -5018,13 +5017,14 @@ static void process_preprocessor_entities(Context *c, ZigClangASTUnit *zunit) { |
| 5018 | 5017 | } |
| 5019 | 5018 | } |
| 5020 | 5019 | |
| 5021 | Error parse_h_file(CodeGen *codegen, AstNode **out_root_node, const char **args_begin, const char **args_end, | |
| 5022 | Stage2TranslateMode mode, ZigList<ErrorMsg *> *errors) | |
| 5020 | Error parse_h_file(CodeGen *codegen, AstNode **out_root_node, | |
| 5021 | Stage2ErrorMsg **errors_ptr, size_t *errors_len, | |
| 5022 | const char **args_begin, const char **args_end, | |
| 5023 | Stage2TranslateMode mode, const char *resources_path) | |
| 5023 | 5024 | { |
| 5024 | 5025 | Context context = {0}; |
| 5025 | 5026 | Context *c = &context; |
| 5026 | 5027 | c->warnings_on = codegen->verbose_cimport; |
| 5027 | c->errors = errors; | |
| 5028 | 5028 | if (mode == Stage2TranslateModeImport) { |
| 5029 | 5029 | c->visib_mod = VisibModPub; |
| 5030 | 5030 | c->want_export = false; |
| ... | ... | @@ -5039,78 +5039,10 @@ Error parse_h_file(CodeGen *codegen, AstNode **out_root_node, const char **args_ |
| 5039 | 5039 | c->codegen = codegen; |
| 5040 | 5040 | c->global_scope = trans_scope_root_create(c); |
| 5041 | 5041 | |
| 5042 | ||
| 5043 | clang::IntrusiveRefCntPtr<clang::DiagnosticsEngine> diags(clang::CompilerInstance::createDiagnostics(new clang::DiagnosticOptions)); | |
| 5044 | ||
| 5045 | std::shared_ptr<clang::PCHContainerOperations> pch_container_ops = std::make_shared<clang::PCHContainerOperations>(); | |
| 5046 | ||
| 5047 | bool only_local_decls = true; | |
| 5048 | bool capture_diagnostics = true; | |
| 5049 | bool user_files_are_volatile = true; | |
| 5050 | bool allow_pch_with_compiler_errors = false; | |
| 5051 | bool single_file_parse = false; | |
| 5052 | bool for_serialization = false; | |
| 5053 | const char *resources_path = buf_ptr(codegen->zig_c_headers_dir); | |
| 5054 | std::unique_ptr<clang::ASTUnit> err_unit; | |
| 5055 | ZigClangASTUnit *ast_unit = reinterpret_cast<ZigClangASTUnit *>(clang::ASTUnit::LoadFromCommandLine( | |
| 5056 | args_begin, args_end, | |
| 5057 | pch_container_ops, diags, resources_path, | |
| 5058 | only_local_decls, capture_diagnostics, clang::None, true, 0, clang::TU_Complete, | |
| 5059 | false, false, allow_pch_with_compiler_errors, clang::SkipFunctionBodiesScope::None, | |
| 5060 | single_file_parse, user_files_are_volatile, for_serialization, clang::None, &err_unit, | |
| 5061 | nullptr)); | |
| 5062 | ||
| 5063 | // Early failures in LoadFromCommandLine may return with ErrUnit unset. | |
| 5064 | if (!ast_unit && !err_unit) { | |
| 5065 | return ErrorFileSystem; | |
| 5066 | } | |
| 5067 | ||
| 5068 | if (diags->getClient()->getNumErrors() > 0) { | |
| 5069 | if (ast_unit) { | |
| 5070 | err_unit = std::unique_ptr<clang::ASTUnit>(reinterpret_cast<clang::ASTUnit *>(ast_unit)); | |
| 5071 | } | |
| 5072 | ||
| 5073 | for (clang::ASTUnit::stored_diag_iterator it = err_unit->stored_diag_begin(), | |
| 5074 | it_end = err_unit->stored_diag_end(); | |
| 5075 | it != it_end; ++it) | |
| 5076 | { | |
| 5077 | switch (it->getLevel()) { | |
| 5078 | case clang::DiagnosticsEngine::Ignored: | |
| 5079 | case clang::DiagnosticsEngine::Note: | |
| 5080 | case clang::DiagnosticsEngine::Remark: | |
| 5081 | case clang::DiagnosticsEngine::Warning: | |
| 5082 | continue; | |
| 5083 | case clang::DiagnosticsEngine::Error: | |
| 5084 | case clang::DiagnosticsEngine::Fatal: | |
| 5085 | break; | |
| 5086 | } | |
| 5087 | llvm::StringRef msg_str_ref = it->getMessage(); | |
| 5088 | Buf *msg = string_ref_to_buf(msg_str_ref); | |
| 5089 | clang::FullSourceLoc fsl = it->getLocation(); | |
| 5090 | if (fsl.hasManager()) { | |
| 5091 | clang::FileID file_id = fsl.getFileID(); | |
| 5092 | clang::StringRef filename = fsl.getManager().getFilename(fsl); | |
| 5093 | unsigned line = fsl.getSpellingLineNumber() - 1; | |
| 5094 | unsigned column = fsl.getSpellingColumnNumber() - 1; | |
| 5095 | unsigned offset = fsl.getManager().getFileOffset(fsl); | |
| 5096 | const char *source = (const char *)fsl.getManager().getBufferData(file_id).bytes_begin(); | |
| 5097 | Buf *path; | |
| 5098 | if (filename.empty()) { | |
| 5099 | path = buf_alloc(); | |
| 5100 | } else { | |
| 5101 | path = string_ref_to_buf(filename); | |
| 5102 | } | |
| 5103 | ||
| 5104 | ErrorMsg *err_msg = err_msg_create_with_offset(path, line, column, offset, source, msg); | |
| 5105 | ||
| 5106 | c->errors->append(err_msg); | |
| 5107 | } else { | |
| 5108 | // NOTE the only known way this gets triggered right now is if you have a lot of errors | |
| 5109 | // clang emits "too many errors emitted, stopping now" | |
| 5110 | fprintf(stderr, "unexpected error from clang: %s\n", buf_ptr(msg)); | |
| 5111 | } | |
| 5112 | } | |
| 5113 | ||
| 5042 | ZigClangASTUnit *ast_unit = ZigClangLoadFromCommandLine(args_begin, args_end, errors_ptr, errors_len, | |
| 5043 | resources_path); | |
| 5044 | if (ast_unit == nullptr) { | |
| 5045 | if (*errors_len == 0) return ErrorNoMem; | |
| 5114 | 5046 | return ErrorCCompileErrors; |
| 5115 | 5047 | } |
| 5116 | 5048 |
src/translate_c.hpp+4-2| ... | ... | @@ -11,7 +11,9 @@ |
| 11 | 11 | |
| 12 | 12 | #include "all_types.hpp" |
| 13 | 13 | |
| 14 | Error parse_h_file(CodeGen *codegen, AstNode **out_root_node, const char **args_begin, const char **args_end, | |
| 15 | Stage2TranslateMode mode, ZigList<ErrorMsg *> *errors); | |
| 14 | Error parse_h_file(CodeGen *codegen, AstNode **out_root_node, | |
| 15 | Stage2ErrorMsg **errors_ptr, size_t *errors_len, | |
| 16 | const char **args_begin, const char **args_end, | |
| 17 | Stage2TranslateMode mode, const char *resources_path); | |
| 16 | 18 | |
| 17 | 19 | #endif |
src/userland.cpp+8-1| ... | ... | @@ -8,12 +8,19 @@ |
| 8 | 8 | #include <string.h> |
| 9 | 9 | |
| 10 | 10 | Error stage2_translate_c(struct Stage2Ast **out_ast, |
| 11 | const char **args_begin, const char **args_end, enum Stage2TranslateMode mode) | |
| 11 | struct Stage2ErrorMsg **out_errors_ptr, size_t *out_errors_len, | |
| 12 | const char **args_begin, const char **args_end, enum Stage2TranslateMode mode, | |
| 13 | const char *resources_path) | |
| 12 | 14 | { |
| 13 | 15 | const char *msg = "stage0 called stage2_translate_c"; |
| 14 | 16 | stage2_panic(msg, strlen(msg)); |
| 15 | 17 | } |
| 16 | 18 | |
| 19 | void stage2_free_clang_errors(struct Stage2ErrorMsg *ptr, size_t len) { | |
| 20 | const char *msg = "stage0 called stage2_free_clang_errors"; | |
| 21 | stage2_panic(msg, strlen(msg)); | |
| 22 | } | |
| 23 | ||
| 17 | 24 | void stage2_zen(const char **ptr, size_t *len) { |
| 18 | 25 | const char *msg = "stage0 called stage2_zen"; |
| 19 | 26 | stage2_panic(msg, strlen(msg)); |
src/userland.h+35-11| ... | ... | @@ -12,20 +12,21 @@ |
| 12 | 12 | #include <stdio.h> |
| 13 | 13 | |
| 14 | 14 | #ifdef __cplusplus |
| 15 | #define ZIG_USERLAND_EXTERN_C extern "C" | |
| 15 | #define ZIG_EXTERN_C extern "C" | |
| 16 | 16 | #else |
| 17 | #define ZIG_USERLAND_EXTERN_C | |
| 17 | #define ZIG_EXTERN_C | |
| 18 | 18 | #endif |
| 19 | 19 | |
| 20 | 20 | #if defined(_MSC_VER) |
| 21 | #define ZIG_USERLAND_ATTRIBUTE_NORETURN __declspec(noreturn) | |
| 21 | #define ZIG_ATTRIBUTE_NORETURN __declspec(noreturn) | |
| 22 | 22 | #else |
| 23 | #define ZIG_USERLAND_ATTRIBUTE_NORETURN __attribute__((noreturn)) | |
| 23 | #define ZIG_ATTRIBUTE_NORETURN __attribute__((noreturn)) | |
| 24 | 24 | #endif |
| 25 | 25 | |
| 26 | // The types and declarations in this file must match both those in userland.cpp and | |
| 27 | // src-self-hosted/stage1.zig. | |
| 26 | // ABI warning: the types and declarations in this file must match both those in | |
| 27 | // userland.cpp and src-self-hosted/stage1.zig. | |
| 28 | 28 | |
| 29 | // ABI warning | |
| 29 | 30 | enum Error { |
| 30 | 31 | ErrorNone, |
| 31 | 32 | ErrorNoMem, |
| ... | ... | @@ -74,20 +75,43 @@ enum Error { |
| 74 | 75 | ErrorNoSpaceLeft, |
| 75 | 76 | }; |
| 76 | 77 | |
| 78 | // ABI warning | |
| 77 | 79 | enum Stage2TranslateMode { |
| 78 | 80 | Stage2TranslateModeImport, |
| 79 | 81 | Stage2TranslateModeTranslate, |
| 80 | 82 | }; |
| 81 | 83 | |
| 84 | // ABI warning | |
| 85 | struct Stage2ErrorMsg { | |
| 86 | const char *filename_ptr; // can be null | |
| 87 | size_t filename_len; | |
| 88 | const char *msg_ptr; | |
| 89 | size_t msg_len; | |
| 90 | const char *source; // valid until the ASTUnit is freed. can be null | |
| 91 | unsigned line; // 0 based | |
| 92 | unsigned column; // 0 based | |
| 93 | unsigned offset; // byte offset into source | |
| 94 | }; | |
| 95 | ||
| 96 | // ABI warning | |
| 82 | 97 | struct Stage2Ast; |
| 83 | 98 | |
| 84 | ZIG_USERLAND_EXTERN_C Error stage2_translate_c(struct Stage2Ast **out_ast, | |
| 85 | const char **args_begin, const char **args_end, enum Stage2TranslateMode mode); | |
| 99 | // ABI warning | |
| 100 | ZIG_EXTERN_C enum Error stage2_translate_c(struct Stage2Ast **out_ast, | |
| 101 | struct Stage2ErrorMsg **out_errors_ptr, size_t *out_errors_len, | |
| 102 | const char **args_begin, const char **args_end, enum Stage2TranslateMode mode, | |
| 103 | const char *resources_path); | |
| 104 | ||
| 105 | // ABI warning | |
| 106 | ZIG_EXTERN_C void stage2_free_clang_errors(struct Stage2ErrorMsg *ptr, size_t len); | |
| 86 | 107 | |
| 87 | ZIG_USERLAND_EXTERN_C void stage2_render_ast(struct Stage2Ast *ast, FILE *output_file); | |
| 108 | // ABI warning | |
| 109 | ZIG_EXTERN_C void stage2_render_ast(struct Stage2Ast *ast, FILE *output_file); | |
| 88 | 110 | |
| 89 | ZIG_USERLAND_EXTERN_C void stage2_zen(const char **ptr, size_t *len); | |
| 111 | // ABI warning | |
| 112 | ZIG_EXTERN_C void stage2_zen(const char **ptr, size_t *len); | |
| 90 | 113 | |
| 91 | ZIG_USERLAND_EXTERN_C ZIG_USERLAND_ATTRIBUTE_NORETURN void stage2_panic(const char *ptr, size_t len); | |
| 114 | // ABI warning | |
| 115 | ZIG_EXTERN_C ZIG_ATTRIBUTE_NORETURN void stage2_panic(const char *ptr, size_t len); | |
| 92 | 116 | |
| 93 | 117 | #endif |
src/zig_clang.cpp+112| ... | ... | @@ -1147,3 +1147,115 @@ ZigClangAPValueLValueBase ZigClangAPValue_getLValueBase(const ZigClangAPValue *s |
| 1147 | 1147 | clang::APValue::LValueBase lval_base = casted->getLValueBase(); |
| 1148 | 1148 | return bitcast(lval_base); |
| 1149 | 1149 | } |
| 1150 | ||
| 1151 | ZigClangASTUnit *ZigClangLoadFromCommandLine(const char **args_begin, const char **args_end, | |
| 1152 | struct Stage2ErrorMsg **errors_ptr, size_t *errors_len, const char *resources_path) | |
| 1153 | { | |
| 1154 | clang::IntrusiveRefCntPtr<clang::DiagnosticsEngine> diags(clang::CompilerInstance::createDiagnostics(new clang::DiagnosticOptions)); | |
| 1155 | ||
| 1156 | std::shared_ptr<clang::PCHContainerOperations> pch_container_ops = std::make_shared<clang::PCHContainerOperations>(); | |
| 1157 | ||
| 1158 | bool only_local_decls = true; | |
| 1159 | bool capture_diagnostics = true; | |
| 1160 | bool user_files_are_volatile = true; | |
| 1161 | bool allow_pch_with_compiler_errors = false; | |
| 1162 | bool single_file_parse = false; | |
| 1163 | bool for_serialization = false; | |
| 1164 | std::unique_ptr<clang::ASTUnit> *err_unit = new std::unique_ptr<clang::ASTUnit>(); | |
| 1165 | clang::ASTUnit *ast_unit = clang::ASTUnit::LoadFromCommandLine( | |
| 1166 | args_begin, args_end, | |
| 1167 | pch_container_ops, diags, resources_path, | |
| 1168 | only_local_decls, capture_diagnostics, clang::None, true, 0, clang::TU_Complete, | |
| 1169 | false, false, allow_pch_with_compiler_errors, clang::SkipFunctionBodiesScope::None, | |
| 1170 | single_file_parse, user_files_are_volatile, for_serialization, clang::None, err_unit, | |
| 1171 | nullptr); | |
| 1172 | ||
| 1173 | // Early failures in LoadFromCommandLine may return with ErrUnit unset. | |
| 1174 | if (!ast_unit && !err_unit) { | |
| 1175 | return nullptr; | |
| 1176 | } | |
| 1177 | ||
| 1178 | if (diags->getClient()->getNumErrors() > 0) { | |
| 1179 | if (ast_unit) { | |
| 1180 | *err_unit = std::unique_ptr<clang::ASTUnit>(ast_unit); | |
| 1181 | } | |
| 1182 | ||
| 1183 | size_t cap = 4; | |
| 1184 | *errors_len = 0; | |
| 1185 | *errors_ptr = reinterpret_cast<Stage2ErrorMsg*>(malloc(cap * sizeof(Stage2ErrorMsg))); | |
| 1186 | if (*errors_ptr == nullptr) { | |
| 1187 | return nullptr; | |
| 1188 | } | |
| 1189 | ||
| 1190 | for (clang::ASTUnit::stored_diag_iterator it = (*err_unit)->stored_diag_begin(), | |
| 1191 | it_end = (*err_unit)->stored_diag_end(); | |
| 1192 | it != it_end; ++it) | |
| 1193 | { | |
| 1194 | switch (it->getLevel()) { | |
| 1195 | case clang::DiagnosticsEngine::Ignored: | |
| 1196 | case clang::DiagnosticsEngine::Note: | |
| 1197 | case clang::DiagnosticsEngine::Remark: | |
| 1198 | case clang::DiagnosticsEngine::Warning: | |
| 1199 | continue; | |
| 1200 | case clang::DiagnosticsEngine::Error: | |
| 1201 | case clang::DiagnosticsEngine::Fatal: | |
| 1202 | break; | |
| 1203 | } | |
| 1204 | llvm::StringRef msg_str_ref = it->getMessage(); | |
| 1205 | if (*errors_len >= cap) { | |
| 1206 | cap *= 2; | |
| 1207 | Stage2ErrorMsg *new_errors = reinterpret_cast<Stage2ErrorMsg *>( | |
| 1208 | realloc(*errors_ptr, cap * sizeof(Stage2ErrorMsg))); | |
| 1209 | if (new_errors == nullptr) { | |
| 1210 | free(*errors_ptr); | |
| 1211 | *errors_ptr = nullptr; | |
| 1212 | *errors_len = 0; | |
| 1213 | return nullptr; | |
| 1214 | } | |
| 1215 | *errors_ptr = new_errors; | |
| 1216 | } | |
| 1217 | Stage2ErrorMsg *msg = *errors_ptr + *errors_len; | |
| 1218 | *errors_len += 1; | |
| 1219 | msg->msg_ptr = (const char *)msg_str_ref.bytes_begin(); | |
| 1220 | msg->msg_len = msg_str_ref.size(); | |
| 1221 | ||
| 1222 | clang::FullSourceLoc fsl = it->getLocation(); | |
| 1223 | if (fsl.hasManager()) { | |
| 1224 | clang::FileID file_id = fsl.getFileID(); | |
| 1225 | clang::StringRef filename = fsl.getManager().getFilename(fsl); | |
| 1226 | if (filename.empty()) { | |
| 1227 | msg->filename_ptr = nullptr; | |
| 1228 | } else { | |
| 1229 | msg->filename_ptr = (const char *)filename.bytes_begin(); | |
| 1230 | msg->filename_len = filename.size(); | |
| 1231 | } | |
| 1232 | msg->source = (const char *)fsl.getManager().getBufferData(file_id).bytes_begin(); | |
| 1233 | msg->line = fsl.getSpellingLineNumber() - 1; | |
| 1234 | msg->column = fsl.getSpellingColumnNumber() - 1; | |
| 1235 | msg->offset = fsl.getManager().getFileOffset(fsl); | |
| 1236 | } else { | |
| 1237 | // The only known way this gets triggered right now is if you have a lot of errors | |
| 1238 | // clang emits "too many errors emitted, stopping now" | |
| 1239 | msg->filename_ptr = nullptr; | |
| 1240 | msg->source = nullptr; | |
| 1241 | } | |
| 1242 | } | |
| 1243 | ||
| 1244 | if (*errors_len == 0) { | |
| 1245 | free(*errors_ptr); | |
| 1246 | *errors_ptr = nullptr; | |
| 1247 | } | |
| 1248 | ||
| 1249 | return nullptr; | |
| 1250 | } | |
| 1251 | ||
| 1252 | return reinterpret_cast<ZigClangASTUnit *>(ast_unit); | |
| 1253 | } | |
| 1254 | ||
| 1255 | void ZigClangErrorMsg_delete(Stage2ErrorMsg *ptr, size_t len) { | |
| 1256 | free(ptr); | |
| 1257 | } | |
| 1258 | ||
| 1259 | void ZigClangASTUnit_delete(struct ZigClangASTUnit *self) { | |
| 1260 | delete reinterpret_cast<clang::ASTUnit *>(self); | |
| 1261 | } |
src/zig_clang.h+8-6| ... | ... | @@ -8,15 +8,10 @@ |
| 8 | 8 | #ifndef ZIG_ZIG_CLANG_H |
| 9 | 9 | #define ZIG_ZIG_CLANG_H |
| 10 | 10 | |
| 11 | #include "userland.h" | |
| 11 | 12 | #include <inttypes.h> |
| 12 | 13 | #include <stdbool.h> |
| 13 | 14 | |
| 14 | #ifdef __cplusplus | |
| 15 | #define ZIG_EXTERN_C extern "C" | |
| 16 | #else | |
| 17 | #define ZIG_EXTERN_C | |
| 18 | #endif | |
| 19 | ||
| 20 | 15 | // ATTENTION: If you modify this file, be sure to update the corresponding |
| 21 | 16 | // extern function declarations in the self-hosted compiler file |
| 22 | 17 | // src-self-hosted/clang.zig. |
| ... | ... | @@ -500,6 +495,13 @@ ZIG_EXTERN_C const char* ZigClangSourceManager_getCharacterData(const struct Zig |
| 500 | 495 | |
| 501 | 496 | ZIG_EXTERN_C struct ZigClangQualType ZigClangASTContext_getPointerType(const struct ZigClangASTContext*, struct ZigClangQualType T); |
| 502 | 497 | |
| 498 | ||
| 499 | // Can return null. | |
| 500 | ZIG_EXTERN_C struct ZigClangASTUnit *ZigClangLoadFromCommandLine(const char **args_begin, const char **args_end, | |
| 501 | struct Stage2ErrorMsg **errors_ptr, size_t *errors_len, const char *resources_path); | |
| 502 | ZIG_EXTERN_C void ZigClangASTUnit_delete(struct ZigClangASTUnit *); | |
| 503 | ZIG_EXTERN_C void ZigClangErrorMsg_delete(struct Stage2ErrorMsg *ptr, size_t len); | |
| 504 | ||
| 503 | 505 | ZIG_EXTERN_C struct ZigClangASTContext *ZigClangASTUnit_getASTContext(struct ZigClangASTUnit *); |
| 504 | 506 | ZIG_EXTERN_C struct ZigClangSourceManager *ZigClangASTUnit_getSourceManager(struct ZigClangASTUnit *); |
| 505 | 507 | ZIG_EXTERN_C bool ZigClangASTUnit_visitLocalTopLevelDecls(struct ZigClangASTUnit *, void *context, |