authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-04-21 19:37:39-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-04-25 00:06:57-04:00
log712274997e80a93bdfe204f2238c4cfaac72a5b8
tree1931c87f8222bb961e6a530e277f7a30ef56c2c8
parent976080462cf62f6f112d38176b99e5bb8a57bf37
signature Commit is signed but in an unrecognized format.

translate-c: unify API for self-hosted and C++ translate-c

See #1964

12 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,6 +862,7 @@ pub extern fn ZigClangAPSInt_free(self: ?*const struct_ZigClangAPSInt) void;
862pub extern fn ZigClangAPSInt_getRawData(self: ?*const struct_ZigClangAPSInt) [*c]const u64;862pub extern fn ZigClangAPSInt_getRawData(self: ?*const struct_ZigClangAPSInt) [*c]const u64;
863pub extern fn ZigClangAPSInt_getNumWords(self: ?*const struct_ZigClangAPSInt) c_uint;863pub extern fn ZigClangAPSInt_getNumWords(self: ?*const struct_ZigClangAPSInt) c_uint;
864pub extern fn ZigClangAPValueLValueBase_dyn_cast_Expr(self: struct_ZigClangAPValueLValueBase) ?*const struct_ZigClangExpr;864pub extern fn ZigClangAPValueLValueBase_dyn_cast_Expr(self: struct_ZigClangAPValueLValueBase) ?*const struct_ZigClangExpr;
865pub extern fn ZigClangASTUnit_delete(arg0: ?*struct_ZigClangASTUnit) void;
865pub const ZigClangSourceLocation = struct_ZigClangSourceLocation;866pub const ZigClangSourceLocation = struct_ZigClangSourceLocation;
866pub const ZigClangQualType = struct_ZigClangQualType;867pub const ZigClangQualType = struct_ZigClangQualType;
867pub const ZigClangAPValueLValueBase = struct_ZigClangAPValueLValueBase;868pub const ZigClangAPValueLValueBase = struct_ZigClangAPValueLValueBase;
...@@ -942,3 +943,19 @@ pub const ZigClangTypeClass = enum_ZigClangTypeClass;...@@ -942,3 +943,19 @@ pub const ZigClangTypeClass = enum_ZigClangTypeClass;
942pub const ZigClangStmtClass = enum_ZigClangStmtClass;943pub const ZigClangStmtClass = enum_ZigClangStmtClass;
943pub const ZigClangCK = enum_ZigClangCK;944pub const ZigClangCK = enum_ZigClangCK;
944pub const ZigClangAPValueKind = enum_ZigClangAPValueKind;945pub const ZigClangAPValueKind = enum_ZigClangAPValueKind;
946
947pub 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};
961pub 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,7 +858,23 @@ fn cmdHelp(allocator: *Allocator, args: []const []const u8) !void {
858 try stdout.write(usage);858 try stdout.write(usage);
859}859}
860860
861const info_zen = @import("stage1.zig").info_zen;861pub 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
862fn cmdZen(allocator: *Allocator, args: []const []const u8) !void {878fn cmdZen(allocator: *Allocator, args: []const []const u8) !void {
863 try stdout.write(info_zen);879 try stdout.write(info_zen);
864}880}
src-self-hosted/stage1.zig+16-19
...@@ -3,37 +3,25 @@...@@ -3,37 +3,25 @@
33
4const std = @import("std");4const std = @import("std");
55
6pub const info_zen =6// ABI warning
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
23export fn stage2_zen(ptr: *[*]const u8, len: *usize) void {7export fn stage2_zen(ptr: *[*]const u8, len: *usize) void {
8 const info_zen = @import("main.zig").info_zen;
24 ptr.* = &info_zen;9 ptr.* = &info_zen;
25 len.* = info_zen.len;10 len.* = info_zen.len;
26}11}
2712
13// ABI warning
28export fn stage2_panic(ptr: [*]const u8, len: usize) void {14export fn stage2_panic(ptr: [*]const u8, len: usize) void {
29 @panic(ptr[0..len]);15 @panic(ptr[0..len]);
30}16}
3117
18// ABI warning
32const TranslateMode = extern enum {19const TranslateMode = extern enum {
33 import,20 import,
34 translate,21 translate,
35};22};
3623
24// ABI warning
37const Error = extern enum {25const Error = extern enum {
38 None,26 None,
39 OutOfMemory,27 OutOfMemory,
...@@ -84,24 +72,33 @@ const Error = extern enum {...@@ -84,24 +72,33 @@ const Error = extern enum {
8472
85const FILE = std.c.FILE;73const FILE = std.c.FILE;
86const ast = std.zig.ast;74const ast = std.zig.ast;
75const translate_c = @import("translate_c.zig");
8776
88/// Args should have a null terminating last arg.77/// Args should have a null terminating last arg.
89export fn stage2_translate_c(78export fn stage2_translate_c(
90 out_ast: **ast.Tree,79 out_ast: **ast.Tree,
80 out_errors_ptr: *[*]translate_c.ClangErrMsg,
81 out_errors_len: *usize,
91 args_begin: [*]?[*]const u8,82 args_begin: [*]?[*]const u8,
92 args_end: [*]?[*]const u8,83 args_end: [*]?[*]const u8,
93 mode: TranslateMode,84 mode: TranslateMode,
85 resources_path: [*]const u8,
94) Error {86) Error {
95 const translate_c = @import("translate_c.zig");87 var errors: []translate_c.ClangErrMsg = undefined;
96 out_ast.* = translate_c.translate(args_begin, args_end, switch (mode) {88 out_ast.* = translate_c.translate(args_begin, args_end, switch (mode) {
97 .import => translate_c.Mode.import,89 .import => translate_c.Mode.import,
98 .translate => translate_c.Mode.translate,90 .translate => translate_c.Mode.translate,
99 }) catch |err| switch (err) {91 }, &errors) catch |err| switch (err) {
100 error.Unimplemented => return Error.Unimplemented,92 error.Unimplemented => return Error.Unimplemented,
101 };93 };
94
102 return Error.None;95 return Error.None;
103}96}
10497
98export 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
105export fn stage2_render_ast(tree: *ast.Tree, output_file: *FILE) Error {102export fn stage2_render_ast(tree: *ast.Tree, output_file: *FILE) Error {
106 const c_out_stream = &std.io.COutStream.init(output_file).stream;103 const c_out_stream = &std.io.COutStream.init(output_file).stream;
107 _ = std.zig.render(std.heap.c_allocator, c_out_stream, tree) catch |e| switch (e) {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,6 +10,17 @@ pub const Mode = enum {
10 translate,10 translate,
11};11};
1212
13pub fn translate(args_begin: [*]?[*]const u8, args_end: [*]?[*]const u8, mode: Mode) !*ast.Tree {13pub const ClangErrMsg = Stage2ErrorMsg;
14
15pub fn translate(
16 args_begin: [*]?[*]const u8,
17 args_end: [*]?[*]const u8,
18 mode: Mode,
19 errors: *[]ClangErrMsg,
20) !*ast.Tree {
14 return error.Unimplemented;21 return error.Unimplemented;
15}22}
23
24pub 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,31 +8298,42 @@ void codegen_translate_c(CodeGen *g, Buf *full_path, FILE *out_file, bool use_us
82988298
8299 clang_argv.append(nullptr); // to make the [start...end] argument work8299 clang_argv.append(nullptr); // to make the [start...end] argument work
83008300
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 if (use_userland_implementation) {8307 if (use_userland_implementation) {
8302 Stage2Ast *ast;8308 err = stage2_translate_c(&ast, &errors_ptr, &errors_len,
8303 if ((err = stage2_translate_c(&ast, &clang_argv.at(0), &clang_argv.last(), trans_mode))) {8309 &clang_argv.at(0), &clang_argv.last(), trans_mode, resources_path);
8304 zig_panic("TODO");
8305 }
8306 stage2_render_ast(ast, out_file);
8307 } else {8310 } else {
8308 ZigList<ErrorMsg *> errors = {0};8311 err = parse_h_file(g, &root_node, &errors_ptr, &errors_len, &clang_argv.at(0), &clang_argv.last(),
8309 AstNode *root_node;8312 trans_mode, resources_path);
83108313 }
8311 err = parse_h_file(g, &root_node, &clang_argv.at(0), &clang_argv.last(), trans_mode, &errors);
83128314
8313 if (err == ErrorCCompileErrors && errors.length > 0) {8315 if (err == ErrorCCompileErrors && errors_len > 0) {
8314 for (size_t i = 0; i < errors.length; i += 1) {8316 for (size_t i = 0; i < errors_len; i += 1) {
8315 ErrorMsg *err_msg = errors.at(i);8317 Stage2ErrorMsg *clang_err = &errors_ptr[i];
8316 print_err_msg(err_msg, g->err_color);8318 ErrorMsg *err_msg = err_msg_create_with_offset(
8317 }8319 clang_err->filename_ptr ?
8318 exit(1);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 }
83208327
8321 if (err) {8328 if (err) {
8322 fprintf(stderr, "unable to parse C file: %s\n", err_str(err));8329 fprintf(stderr, "unable to parse C file: %s\n", err_str(err));
8323 exit(1);8330 exit(1);
8324 }8331 }
83258332
8333
8334 if (use_userland_implementation) {
8335 stage2_render_ast(ast, out_file);
8336 } else {
8326 ast_render(out_file, root_node, 4);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,25 +19103,32 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct
1910319103
19104 clang_argv.append(nullptr); // to make the [start...end] argument work19104 clang_argv.append(nullptr); // to make the [start...end] argument work
1910519105
19106 ZigList<ErrorMsg *> errors = {0};
19107 AstNode *root_node;19106 AstNode *root_node;
19107 Stage2ErrorMsg *errors_ptr;
19108 size_t errors_len;
1910819109
19109 if ((err = parse_h_file(ira->codegen, &root_node, &clang_argv.at(0), &clang_argv.last(),19110 const char *resources_path = buf_ptr(ira->codegen->zig_c_headers_dir);
19110 Stage2TranslateModeImport, &errors)))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 if (err != ErrorCCompileErrors) {19115 if (err != ErrorCCompileErrors) {
19113 ir_add_error_node(ira, node, buf_sprintf("C import failed: %s", err_str(err)));19116 ir_add_error_node(ira, node, buf_sprintf("C import failed: %s", err_str(err)));
19114 return ira->codegen->invalid_instruction;19117 return ira->codegen->invalid_instruction;
19115 }19118 }
19116 assert(errors.length > 0);
1911719119
19118 ErrorMsg *parent_err_msg = ir_add_error_node(ira, node, buf_sprintf("C import failed"));19120 ErrorMsg *parent_err_msg = ir_add_error_node(ira, node, buf_sprintf("C import failed"));
19119 if (ira->codegen->libc_link_lib == nullptr) {19121 if (ira->codegen->libc_link_lib == nullptr) {
19120 add_error_note(ira->codegen, parent_err_msg, node,19122 add_error_note(ira->codegen, parent_err_msg, node,
19121 buf_sprintf("libc headers not available; compilation does not link against libc"));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) {19125 for (size_t i = 0; i < errors_len; i += 1) {
19124 ErrorMsg *err_msg = errors.at(i);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 err_msg_add_note(parent_err_msg, err_msg);19132 err_msg_add_note(parent_err_msg, err_msg);
19126 }19133 }
1912719134
src/translate_c.cpp+9-77
...@@ -76,10 +76,9 @@ struct TransScopeWhile {...@@ -76,10 +76,9 @@ struct TransScopeWhile {
76};76};
7777
78struct Context {78struct Context {
79 ZigList<ErrorMsg *> *errors;79 AstNode *root;
80 VisibMod visib_mod;80 VisibMod visib_mod;
81 bool want_export;81 bool want_export;
82 AstNode *root;
83 HashMap<const void *, AstNode *, ptr_hash, ptr_eq> decl_table;82 HashMap<const void *, AstNode *, ptr_hash, ptr_eq> decl_table;
84 HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> macro_table;83 HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> macro_table;
85 HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> global_table;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,13 +5017,14 @@ static void process_preprocessor_entities(Context *c, ZigClangASTUnit *zunit) {
5018 }5017 }
5019}5018}
50205019
5021Error parse_h_file(CodeGen *codegen, AstNode **out_root_node, const char **args_begin, const char **args_end,5020Error parse_h_file(CodeGen *codegen, AstNode **out_root_node,
5022 Stage2TranslateMode mode, ZigList<ErrorMsg *> *errors)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 Context context = {0};5025 Context context = {0};
5025 Context *c = &context;5026 Context *c = &context;
5026 c->warnings_on = codegen->verbose_cimport;5027 c->warnings_on = codegen->verbose_cimport;
5027 c->errors = errors;
5028 if (mode == Stage2TranslateModeImport) {5028 if (mode == Stage2TranslateModeImport) {
5029 c->visib_mod = VisibModPub;5029 c->visib_mod = VisibModPub;
5030 c->want_export = false;5030 c->want_export = false;
...@@ -5039,78 +5039,10 @@ Error parse_h_file(CodeGen *codegen, AstNode **out_root_node, const char **args_...@@ -5039,78 +5039,10 @@ Error parse_h_file(CodeGen *codegen, AstNode **out_root_node, const char **args_
5039 c->codegen = codegen;5039 c->codegen = codegen;
5040 c->global_scope = trans_scope_root_create(c);5040 c->global_scope = trans_scope_root_create(c);
50415041
50425042 ZigClangASTUnit *ast_unit = ZigClangLoadFromCommandLine(args_begin, args_end, errors_ptr, errors_len,
5043 clang::IntrusiveRefCntPtr<clang::DiagnosticsEngine> diags(clang::CompilerInstance::createDiagnostics(new clang::DiagnosticOptions));5043 resources_path);
50445044 if (ast_unit == nullptr) {
5045 std::shared_ptr<clang::PCHContainerOperations> pch_container_ops = std::make_shared<clang::PCHContainerOperations>();5045 if (*errors_len == 0) return ErrorNoMem;
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
5114 return ErrorCCompileErrors;5046 return ErrorCCompileErrors;
5115 }5047 }
51165048
src/translate_c.hpp+4-2
...@@ -11,7 +11,9 @@...@@ -11,7 +11,9 @@
1111
12#include "all_types.hpp"12#include "all_types.hpp"
1313
14Error parse_h_file(CodeGen *codegen, AstNode **out_root_node, const char **args_begin, const char **args_end,14Error parse_h_file(CodeGen *codegen, AstNode **out_root_node,
15 Stage2TranslateMode mode, ZigList<ErrorMsg *> *errors);15 Stage2ErrorMsg **errors_ptr, size_t *errors_len,
16 const char **args_begin, const char **args_end,
17 Stage2TranslateMode mode, const char *resources_path);
1618
17#endif19#endif
src/userland.cpp+8-1
...@@ -8,12 +8,19 @@...@@ -8,12 +8,19 @@
8#include <string.h>8#include <string.h>
99
10Error stage2_translate_c(struct Stage2Ast **out_ast,10Error 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 const char *msg = "stage0 called stage2_translate_c";15 const char *msg = "stage0 called stage2_translate_c";
14 stage2_panic(msg, strlen(msg));16 stage2_panic(msg, strlen(msg));
15}17}
1618
19void 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
17void stage2_zen(const char **ptr, size_t *len) {24void stage2_zen(const char **ptr, size_t *len) {
18 const char *msg = "stage0 called stage2_zen";25 const char *msg = "stage0 called stage2_zen";
19 stage2_panic(msg, strlen(msg));26 stage2_panic(msg, strlen(msg));
src/userland.h+35-11
...@@ -12,20 +12,21 @@...@@ -12,20 +12,21 @@
12#include <stdio.h>12#include <stdio.h>
1313
14#ifdef __cplusplus14#ifdef __cplusplus
15#define ZIG_USERLAND_EXTERN_C extern "C"15#define ZIG_EXTERN_C extern "C"
16#else16#else
17#define ZIG_USERLAND_EXTERN_C17#define ZIG_EXTERN_C
18#endif18#endif
1919
20#if defined(_MSC_VER)20#if defined(_MSC_VER)
21#define ZIG_USERLAND_ATTRIBUTE_NORETURN __declspec(noreturn)21#define ZIG_ATTRIBUTE_NORETURN __declspec(noreturn)
22#else22#else
23#define ZIG_USERLAND_ATTRIBUTE_NORETURN __attribute__((noreturn))23#define ZIG_ATTRIBUTE_NORETURN __attribute__((noreturn))
24#endif24#endif
2525
26// The types and declarations in this file must match both those in userland.cpp and26// ABI warning: the types and declarations in this file must match both those in
27// src-self-hosted/stage1.zig.27// userland.cpp and src-self-hosted/stage1.zig.
2828
29// ABI warning
29enum Error {30enum Error {
30 ErrorNone,31 ErrorNone,
31 ErrorNoMem,32 ErrorNoMem,
...@@ -74,20 +75,43 @@ enum Error {...@@ -74,20 +75,43 @@ enum Error {
74 ErrorNoSpaceLeft,75 ErrorNoSpaceLeft,
75};76};
7677
78// ABI warning
77enum Stage2TranslateMode {79enum Stage2TranslateMode {
78 Stage2TranslateModeImport,80 Stage2TranslateModeImport,
79 Stage2TranslateModeTranslate,81 Stage2TranslateModeTranslate,
80};82};
8183
84// ABI warning
85struct 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
82struct Stage2Ast;97struct Stage2Ast;
8398
84ZIG_USERLAND_EXTERN_C Error stage2_translate_c(struct Stage2Ast **out_ast,99// ABI warning
85 const char **args_begin, const char **args_end, enum Stage2TranslateMode mode);100ZIG_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
106ZIG_EXTERN_C void stage2_free_clang_errors(struct Stage2ErrorMsg *ptr, size_t len);
86107
87ZIG_USERLAND_EXTERN_C void stage2_render_ast(struct Stage2Ast *ast, FILE *output_file);108// ABI warning
109ZIG_EXTERN_C void stage2_render_ast(struct Stage2Ast *ast, FILE *output_file);
88110
89ZIG_USERLAND_EXTERN_C void stage2_zen(const char **ptr, size_t *len);111// ABI warning
112ZIG_EXTERN_C void stage2_zen(const char **ptr, size_t *len);
90113
91ZIG_USERLAND_EXTERN_C ZIG_USERLAND_ATTRIBUTE_NORETURN void stage2_panic(const char *ptr, size_t len);114// ABI warning
115ZIG_EXTERN_C ZIG_ATTRIBUTE_NORETURN void stage2_panic(const char *ptr, size_t len);
92116
93#endif117#endif
src/zig_clang.cpp+112
...@@ -1147,3 +1147,115 @@ ZigClangAPValueLValueBase ZigClangAPValue_getLValueBase(const ZigClangAPValue *s...@@ -1147,3 +1147,115 @@ ZigClangAPValueLValueBase ZigClangAPValue_getLValueBase(const ZigClangAPValue *s
1147 clang::APValue::LValueBase lval_base = casted->getLValueBase();1147 clang::APValue::LValueBase lval_base = casted->getLValueBase();
1148 return bitcast(lval_base);1148 return bitcast(lval_base);
1149}1149}
1150
1151ZigClangASTUnit *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
1255void ZigClangErrorMsg_delete(Stage2ErrorMsg *ptr, size_t len) {
1256 free(ptr);
1257}
1258
1259void ZigClangASTUnit_delete(struct ZigClangASTUnit *self) {
1260 delete reinterpret_cast<clang::ASTUnit *>(self);
1261}
src/zig_clang.h+8-6
...@@ -8,15 +8,10 @@...@@ -8,15 +8,10 @@
8#ifndef ZIG_ZIG_CLANG_H8#ifndef ZIG_ZIG_CLANG_H
9#define ZIG_ZIG_CLANG_H9#define ZIG_ZIG_CLANG_H
1010
11#include "userland.h"
11#include <inttypes.h>12#include <inttypes.h>
12#include <stdbool.h>13#include <stdbool.h>
1314
14#ifdef __cplusplus
15#define ZIG_EXTERN_C extern "C"
16#else
17#define ZIG_EXTERN_C
18#endif
19
20// ATTENTION: If you modify this file, be sure to update the corresponding15// ATTENTION: If you modify this file, be sure to update the corresponding
21// extern function declarations in the self-hosted compiler file16// extern function declarations in the self-hosted compiler file
22// src-self-hosted/clang.zig.17// src-self-hosted/clang.zig.
...@@ -500,6 +495,13 @@ ZIG_EXTERN_C const char* ZigClangSourceManager_getCharacterData(const struct Zig...@@ -500,6 +495,13 @@ ZIG_EXTERN_C const char* ZigClangSourceManager_getCharacterData(const struct Zig
500495
501ZIG_EXTERN_C struct ZigClangQualType ZigClangASTContext_getPointerType(const struct ZigClangASTContext*, struct ZigClangQualType T);496ZIG_EXTERN_C struct ZigClangQualType ZigClangASTContext_getPointerType(const struct ZigClangASTContext*, struct ZigClangQualType T);
502497
498
499// Can return null.
500ZIG_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);
502ZIG_EXTERN_C void ZigClangASTUnit_delete(struct ZigClangASTUnit *);
503ZIG_EXTERN_C void ZigClangErrorMsg_delete(struct Stage2ErrorMsg *ptr, size_t len);
504
503ZIG_EXTERN_C struct ZigClangASTContext *ZigClangASTUnit_getASTContext(struct ZigClangASTUnit *);505ZIG_EXTERN_C struct ZigClangASTContext *ZigClangASTUnit_getASTContext(struct ZigClangASTUnit *);
504ZIG_EXTERN_C struct ZigClangSourceManager *ZigClangASTUnit_getSourceManager(struct ZigClangASTUnit *);506ZIG_EXTERN_C struct ZigClangSourceManager *ZigClangASTUnit_getSourceManager(struct ZigClangASTUnit *);
505ZIG_EXTERN_C bool ZigClangASTUnit_visitLocalTopLevelDecls(struct ZigClangASTUnit *, void *context, 507ZIG_EXTERN_C bool ZigClangASTUnit_visitLocalTopLevelDecls(struct ZigClangASTUnit *, void *context,