parent
976080462c
commit
712274997e
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
err = stage2_translate_c(&ast, &errors_ptr, &errors_len,
|
||||
&clang_argv.at(0), &clang_argv.last(), trans_mode, resources_path);
|
||||
} else {
|
||||
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_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 (use_userland_implementation) {
|
||||
stage2_render_ast(ast, out_file);
|
||||
} else {
|
||||
ZigList<ErrorMsg *> errors = {0};
|
||||
AstNode *root_node;
|
||||
|
||||
err = parse_h_file(g, &root_node, &clang_argv.at(0), &clang_argv.last(), trans_mode, &errors);
|
||||
|
||||
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) {
|
||||
fprintf(stderr, "unable to parse C file: %s\n", err_str(err));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ast_render(out_file, root_node, 4);
|
||||
}
|
||||
}
|
||||
|
|
19
src/ir.cpp
19
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<ErrorMsg *> 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);
|
||||
}
|
||||
|
||||
|
|
|
@ -76,10 +76,9 @@ struct TransScopeWhile {
|
|||
};
|
||||
|
||||
struct Context {
|
||||
ZigList<ErrorMsg *> *errors;
|
||||
AstNode *root;
|
||||
VisibMod visib_mod;
|
||||
bool want_export;
|
||||
AstNode *root;
|
||||
HashMap<const void *, AstNode *, ptr_hash, ptr_eq> decl_table;
|
||||
HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> macro_table;
|
||||
HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> 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<ErrorMsg *> *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<clang::DiagnosticsEngine> diags(clang::CompilerInstance::createDiagnostics(new clang::DiagnosticOptions));
|
||||
|
||||
std::shared_ptr<clang::PCHContainerOperations> pch_container_ops = std::make_shared<clang::PCHContainerOperations>();
|
||||
|
||||
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<clang::ASTUnit> err_unit;
|
||||
ZigClangASTUnit *ast_unit = reinterpret_cast<ZigClangASTUnit *>(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<clang::ASTUnit>(reinterpret_cast<clang::ASTUnit *>(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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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<ErrorMsg *> *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
|
||||
|
|
|
@ -8,12 +8,19 @@
|
|||
#include <string.h>
|
||||
|
||||
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));
|
||||
|
|
|
@ -12,20 +12,21 @@
|
|||
#include <stdio.h>
|
||||
|
||||
#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);
|
||||
|
||||
ZIG_USERLAND_EXTERN_C void stage2_render_ast(struct Stage2Ast *ast, FILE *output_file);
|
||||
// ABI warning
|
||||
ZIG_EXTERN_C void stage2_free_clang_errors(struct Stage2ErrorMsg *ptr, size_t len);
|
||||
|
||||
ZIG_USERLAND_EXTERN_C void stage2_zen(const char **ptr, size_t *len);
|
||||
// ABI warning
|
||||
ZIG_EXTERN_C void stage2_render_ast(struct Stage2Ast *ast, FILE *output_file);
|
||||
|
||||
ZIG_USERLAND_EXTERN_C ZIG_USERLAND_ATTRIBUTE_NORETURN void stage2_panic(const char *ptr, size_t len);
|
||||
// ABI warning
|
||||
ZIG_EXTERN_C void stage2_zen(const char **ptr, size_t *len);
|
||||
|
||||
// ABI warning
|
||||
ZIG_EXTERN_C ZIG_ATTRIBUTE_NORETURN void stage2_panic(const char *ptr, size_t len);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -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<clang::DiagnosticsEngine> diags(clang::CompilerInstance::createDiagnostics(new clang::DiagnosticOptions));
|
||||
|
||||
std::shared_ptr<clang::PCHContainerOperations> pch_container_ops = std::make_shared<clang::PCHContainerOperations>();
|
||||
|
||||
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<clang::ASTUnit> *err_unit = new std::unique_ptr<clang::ASTUnit>();
|
||||
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<clang::ASTUnit>(ast_unit);
|
||||
}
|
||||
|
||||
size_t cap = 4;
|
||||
*errors_len = 0;
|
||||
*errors_ptr = reinterpret_cast<Stage2ErrorMsg*>(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<Stage2ErrorMsg *>(
|
||||
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<ZigClangASTUnit *>(ast_unit);
|
||||
}
|
||||
|
||||
void ZigClangErrorMsg_delete(Stage2ErrorMsg *ptr, size_t len) {
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
void ZigClangASTUnit_delete(struct ZigClangASTUnit *self) {
|
||||
delete reinterpret_cast<clang::ASTUnit *>(self);
|
||||
}
|
||||
|
|
|
@ -8,15 +8,10 @@
|
|||
#ifndef ZIG_ZIG_CLANG_H
|
||||
#define ZIG_ZIG_CLANG_H
|
||||
|
||||
#include "userland.h"
|
||||
#include <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#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,
|
||||
|
|
Loading…
Reference in New Issue