diff --git a/example/hello_world/hello_libc.zig b/example/hello_world/hello_libc.zig index 4dc14398ba..206886d3e8 100644 --- a/example/hello_world/hello_libc.zig +++ b/example/hello_world/hello_libc.zig @@ -1,7 +1,9 @@ #link("c") export executable "hello"; -extern fn printf(__format: &const u8, ...) -> c_int; +c_import { + @c_include("stdio.h"); +} export fn main(argc: c_int, argv: &&u8) -> c_int { printf(c"Hello, world!\n"); diff --git a/src/all_types.hpp b/src/all_types.hpp index c731e5fd99..f592c4c886 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -894,7 +894,7 @@ struct ImportTableEntry { ZigList *line_offsets; BlockContext *block_context; ZigList importers; - bool is_c_import; + AstNode *c_import_node; // reminder: hash tables must be initialized before use HashMap fn_table; diff --git a/src/analyze.cpp b/src/analyze.cpp index 121c4c04ff..6df6c8baed 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -12,6 +12,7 @@ #include "os.hpp" #include "parseh.hpp" #include "config.h" +#include "ast_render.hpp" static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, BlockContext *context, TypeTableEntry *expected_type, AstNode *node); @@ -26,6 +27,7 @@ static TypeTableEntry *analyze_error_literal_expr(CodeGen *g, ImportTableEntry * static TypeTableEntry *analyze_block_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, TypeTableEntry *expected_type, AstNode *node); static TypeTableEntry *resolve_expr_const_val_as_void(CodeGen *g, AstNode *node); +static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode *node); static AstNode *first_executing_node(AstNode *node) { switch (node->type) { @@ -87,6 +89,8 @@ static AstNode *first_executing_node(AstNode *node) { } ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg) { + assert(!node->owner->c_import_node); + ErrorMsg *err = err_msg_create_with_line(node->owner->path, node->line, node->column, node->owner->source_code, node->owner->line_offsets, msg); @@ -1056,11 +1060,15 @@ static void resolve_c_import_decl(CodeGen *g, ImportTableEntry *parent_import, A find_libc_path(g); - ImportTableEntry child_import = {0}; + ImportTableEntry *child_import = allocate(1); + child_import->fn_table.init(32); + child_import->fn_type_table.init(32); + child_import->c_import_node = node; + ZigList errors = {0}; int err; - if ((err = parse_h_buf(&child_import, &errors, child_context->c_import_buf, g->clang_argv, g->clang_argv_len, + if ((err = parse_h_buf(child_import, &errors, child_context->c_import_buf, g->clang_argv, g->clang_argv_len, buf_ptr(g->libc_include_path)))) { zig_panic("unable to parse h file: %s\n", err_str(err)); @@ -1075,7 +1083,24 @@ static void resolve_c_import_decl(CodeGen *g, ImportTableEntry *parent_import, A return; } - zig_panic("TODO integrate the AST"); + if (g->verbose) { + fprintf(stderr, "\nc_import:\n"); + fprintf(stderr, "-----------\n"); + ast_render(stderr, child_import->root, 4); + } + + child_import->di_file = parent_import->di_file; + child_import->block_context = new_block_context(child_import->root, nullptr); + child_import->importers.append({parent_import, node}); + + detect_top_level_decl_deps(g, child_import, child_import->root); +} + +static void satisfy_dep(CodeGen *g, AstNode *node) { + Buf *name = get_resolved_top_level_decl(node)->name; + if (name) { + g->unresolved_top_level_decls.maybe_remove(name); + } } static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode *node) { @@ -1085,7 +1110,7 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode break; case NodeTypeRootExportDecl: // handled earlier - break; + return; case NodeTypeStructDecl: { TypeTableEntry *type_entry = node->data.struct_decl.type_entry; @@ -1115,7 +1140,7 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode break; case NodeTypeImport: // nothing to do here - break; + return; case NodeTypeCImport: resolve_c_import_decl(g, import, node); break; @@ -1159,6 +1184,9 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode case NodeTypeErrorType: zig_unreachable(); } + + + satisfy_dep(g, node); } static FnTableEntry *get_context_fn_entry(BlockContext *context) { @@ -4512,6 +4540,12 @@ static TypeTableEntryId container_to_type(ContainerKind kind) { static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode *node) { switch (node->type) { + case NodeTypeRoot: + for (int i = 0; i < import->root->data.root.top_level_decls.length; i += 1) { + AstNode *child = import->root->data.root.top_level_decls.at(i); + detect_top_level_decl_deps(g, import, child); + } + break; case NodeTypeStructDecl: { Buf *name = &node->data.struct_decl.name; @@ -4664,7 +4698,6 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast case NodeTypeParamDecl: case NodeTypeFnDecl: case NodeTypeReturnExpr: - case NodeTypeRoot: case NodeTypeBlock: case NodeTypeBinOpExpr: case NodeTypeUnwrapErrorExpr: @@ -4732,7 +4765,6 @@ static void recursive_resolve_decl(CodeGen *g, ImportTableEntry *import, AstNode } resolve_top_level_decl(g, import, node); - g->unresolved_top_level_decls.remove(get_resolved_top_level_decl(node)->name); } static void resolve_top_level_declarations_root(CodeGen *g, ImportTableEntry *import, AstNode *node) { @@ -4823,10 +4855,7 @@ void semantic_analyze(CodeGen *g) { ImportTableEntry *import = entry->value; - for (int i = 0; i < import->root->data.root.top_level_decls.length; i += 1) { - AstNode *child = import->root->data.root.top_level_decls.at(i); - detect_top_level_decl_deps(g, import, child); - } + detect_top_level_decl_deps(g, import, import->root); } } diff --git a/src/hash_map.hpp b/src/hash_map.hpp index 0892349adc..74e56e7298 100644 --- a/src/hash_map.hpp +++ b/src/hash_map.hpp @@ -72,6 +72,12 @@ public: return internal_get(key); } + void maybe_remove(const K &key) { + if (maybe_get(key)) { + remove(key); + } + } + void remove(const K &key) { _modification_count += 1; int start_index = key_to_index(key); diff --git a/src/parseh.cpp b/src/parseh.cpp index 49872a97b3..cca9eab869 100644 --- a/src/parseh.cpp +++ b/src/parseh.cpp @@ -27,6 +27,7 @@ struct Context { AstNode *c_void_decl_node; AstNode *root; HashMap type_table; + HashMap fn_table; }; static AstNode *make_qual_type_node(Context *c, QualType qt); @@ -107,8 +108,8 @@ static AstNode *make_type_node(Context *c, const Type *ty) { return simple_type_node(c, "bool"); case BuiltinType::Char_U: case BuiltinType::UChar: - return simple_type_node(c, "u8"); case BuiltinType::Char_S: + return simple_type_node(c, "u8"); case BuiltinType::SChar: return simple_type_node(c, "i8"); case BuiltinType::UShort: @@ -266,11 +267,18 @@ static AstNode *make_qual_type_node(Context *c, QualType qt) { static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) { AstNode *node = create_node(c, NodeTypeFnProto); + buf_init_from_str(&node->data.fn_proto.name, decl_name(fn_decl)); + + auto fn_entry = c->fn_table.maybe_get(&node->data.fn_proto.name); + if (fn_entry) { + // we already saw this function + return; + } + node->data.fn_proto.is_extern = true; node->data.fn_proto.visib_mod = c->visib_mod; node->data.fn_proto.directives = create_empty_directives(c); node->data.fn_proto.is_var_args = fn_decl->isVariadic(); - buf_init_from_str(&node->data.fn_proto.name, decl_name(fn_decl)); int arg_count = fn_decl->getNumParams(); bool all_ok = true; @@ -313,6 +321,7 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) { normalize_parent_ptrs(node); + c->fn_table.put(&node->data.fn_proto.name, true); c->root->data.root.top_level_decls.append(node); } @@ -392,7 +401,9 @@ int parse_h_file(ImportTableEntry *import, ZigList *errors, ZigList< Context *c = &context; c->import = import; c->errors = errors; - c->type_table.init(64); + c->visib_mod = VisibModPub; + c->type_table.init(32); + c->fn_table.init(32); char *ZIG_PARSEH_CFLAGS = getenv("ZIG_PARSEH_CFLAGS"); if (ZIG_PARSEH_CFLAGS) { @@ -486,7 +497,6 @@ int parse_h_file(ImportTableEntry *import, ZigList *errors, ZigList< normalize_parent_ptrs(c->root); import->root = c->root; - import->is_c_import = true; return 0; } diff --git a/test/run_tests.cpp b/test/run_tests.cpp index 73478c6b55..17d45d1203 100644 --- a/test/run_tests.cpp +++ b/test/run_tests.cpp @@ -98,7 +98,11 @@ static void add_compiling_test_cases(void) { add_simple_case("hello world with libc", R"SOURCE( #link("c") export executable "test"; -extern fn puts(s: &const u8) -> c_int; + +c_import { + @c_include("stdio.h"); +} + export fn main(argc: c_int, argv: &&u8) -> c_int { puts(c"Hello, world!"); return 0; @@ -481,7 +485,10 @@ pub fn main(args: [][]u8) -> %void { add_simple_case("number literals", R"SOURCE( #link("c") export executable "test"; -extern fn printf(__format: &const u8, ...) -> c_int; + +c_import { + @c_include("stdio.h"); +} export fn main(argc: c_int, argv: &&u8) -> c_int { printf(c"\n");