authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-27 23:22:37-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-27 23:23:02-07:00
log97c61313dab659e4934e0dd31ffa89284151017b
treefda7c30a0ec9ecdff64b7c0a5f74de776b488368
parent51ab9b03ce97666fd7fd56cf0f81b11fb1709bc6

c_import of stdio.h works for some functions

See #88

6 files changed, 73 insertions(+), 19 deletions(-)

example/hello_world/hello_libc.zig+3-1
......@@ -1,7 +1,9 @@
11#link("c")
22export executable "hello";
33
4extern fn printf(__format: &const u8, ...) -> c_int;
4c_import {
5 @c_include("stdio.h");
6}
57
68export fn main(argc: c_int, argv: &&u8) -> c_int {
79 printf(c"Hello, world!\n");
src/all_types.hpp+1-1
......@@ -894,7 +894,7 @@ struct ImportTableEntry {
894894 ZigList<int> *line_offsets;
895895 BlockContext *block_context;
896896 ZigList<ImporterInfo> importers;
897 bool is_c_import;
897 AstNode *c_import_node;
898898
899899 // reminder: hash tables must be initialized before use
900900 HashMap<Buf *, FnTableEntry *, buf_hash, buf_eql_buf> fn_table;
src/analyze.cpp+40-11
......@@ -12,6 +12,7 @@
1212#include "os.hpp"
1313#include "parseh.hpp"
1414#include "config.h"
15#include "ast_render.hpp"
1516
1617static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, BlockContext *context,
1718 TypeTableEntry *expected_type, AstNode *node);
......@@ -26,6 +27,7 @@ static TypeTableEntry *analyze_error_literal_expr(CodeGen *g, ImportTableEntry *
2627static TypeTableEntry *analyze_block_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
2728 TypeTableEntry *expected_type, AstNode *node);
2829static TypeTableEntry *resolve_expr_const_val_as_void(CodeGen *g, AstNode *node);
30static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode *node);
2931
3032static AstNode *first_executing_node(AstNode *node) {
3133 switch (node->type) {
......@@ -87,6 +89,8 @@ static AstNode *first_executing_node(AstNode *node) {
8789}
8890
8991ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg) {
92 assert(!node->owner->c_import_node);
93
9094 ErrorMsg *err = err_msg_create_with_line(node->owner->path, node->line, node->column,
9195 node->owner->source_code, node->owner->line_offsets, msg);
9296
......@@ -1056,11 +1060,15 @@ static void resolve_c_import_decl(CodeGen *g, ImportTableEntry *parent_import, A
10561060
10571061 find_libc_path(g);
10581062
1059 ImportTableEntry child_import = {0};
1063 ImportTableEntry *child_import = allocate<ImportTableEntry>(1);
1064 child_import->fn_table.init(32);
1065 child_import->fn_type_table.init(32);
1066 child_import->c_import_node = node;
1067
10601068 ZigList<ErrorMsg *> errors = {0};
10611069
10621070 int err;
1063 if ((err = parse_h_buf(&child_import, &errors, child_context->c_import_buf, g->clang_argv, g->clang_argv_len,
1071 if ((err = parse_h_buf(child_import, &errors, child_context->c_import_buf, g->clang_argv, g->clang_argv_len,
10641072 buf_ptr(g->libc_include_path))))
10651073 {
10661074 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
10751083 return;
10761084 }
10771085
1078 zig_panic("TODO integrate the AST");
1086 if (g->verbose) {
1087 fprintf(stderr, "\nc_import:\n");
1088 fprintf(stderr, "-----------\n");
1089 ast_render(stderr, child_import->root, 4);
1090 }
1091
1092 child_import->di_file = parent_import->di_file;
1093 child_import->block_context = new_block_context(child_import->root, nullptr);
1094 child_import->importers.append({parent_import, node});
1095
1096 detect_top_level_decl_deps(g, child_import, child_import->root);
1097}
1098
1099static void satisfy_dep(CodeGen *g, AstNode *node) {
1100 Buf *name = get_resolved_top_level_decl(node)->name;
1101 if (name) {
1102 g->unresolved_top_level_decls.maybe_remove(name);
1103 }
10791104}
10801105
10811106static 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
10851110 break;
10861111 case NodeTypeRootExportDecl:
10871112 // handled earlier
1088 break;
1113 return;
10891114 case NodeTypeStructDecl:
10901115 {
10911116 TypeTableEntry *type_entry = node->data.struct_decl.type_entry;
......@@ -1115,7 +1140,7 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode
11151140 break;
11161141 case NodeTypeImport:
11171142 // nothing to do here
1118 break;
1143 return;
11191144 case NodeTypeCImport:
11201145 resolve_c_import_decl(g, import, node);
11211146 break;
......@@ -1159,6 +1184,9 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode
11591184 case NodeTypeErrorType:
11601185 zig_unreachable();
11611186 }
1187
1188
1189 satisfy_dep(g, node);
11621190}
11631191
11641192static FnTableEntry *get_context_fn_entry(BlockContext *context) {
......@@ -4512,6 +4540,12 @@ static TypeTableEntryId container_to_type(ContainerKind kind) {
45124540
45134541static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode *node) {
45144542 switch (node->type) {
4543 case NodeTypeRoot:
4544 for (int i = 0; i < import->root->data.root.top_level_decls.length; i += 1) {
4545 AstNode *child = import->root->data.root.top_level_decls.at(i);
4546 detect_top_level_decl_deps(g, import, child);
4547 }
4548 break;
45154549 case NodeTypeStructDecl:
45164550 {
45174551 Buf *name = &node->data.struct_decl.name;
......@@ -4664,7 +4698,6 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast
46644698 case NodeTypeParamDecl:
46654699 case NodeTypeFnDecl:
46664700 case NodeTypeReturnExpr:
4667 case NodeTypeRoot:
46684701 case NodeTypeBlock:
46694702 case NodeTypeBinOpExpr:
46704703 case NodeTypeUnwrapErrorExpr:
......@@ -4732,7 +4765,6 @@ static void recursive_resolve_decl(CodeGen *g, ImportTableEntry *import, AstNode
47324765 }
47334766
47344767 resolve_top_level_decl(g, import, node);
4735 g->unresolved_top_level_decls.remove(get_resolved_top_level_decl(node)->name);
47364768}
47374769
47384770static void resolve_top_level_declarations_root(CodeGen *g, ImportTableEntry *import, AstNode *node) {
......@@ -4823,10 +4855,7 @@ void semantic_analyze(CodeGen *g) {
48234855
48244856 ImportTableEntry *import = entry->value;
48254857
4826 for (int i = 0; i < import->root->data.root.top_level_decls.length; i += 1) {
4827 AstNode *child = import->root->data.root.top_level_decls.at(i);
4828 detect_top_level_decl_deps(g, import, child);
4829 }
4858 detect_top_level_decl_deps(g, import, import->root);
48304859 }
48314860 }
48324861
src/hash_map.hpp+6
......@@ -72,6 +72,12 @@ public:
7272 return internal_get(key);
7373 }
7474
75 void maybe_remove(const K &key) {
76 if (maybe_get(key)) {
77 remove(key);
78 }
79 }
80
7581 void remove(const K &key) {
7682 _modification_count += 1;
7783 int start_index = key_to_index(key);
src/parseh.cpp+14-4
......@@ -27,6 +27,7 @@ struct Context {
2727 AstNode *c_void_decl_node;
2828 AstNode *root;
2929 HashMap<Buf *, bool, buf_hash, buf_eql_buf> type_table;
30 HashMap<Buf *, bool, buf_hash, buf_eql_buf> fn_table;
3031};
3132
3233static AstNode *make_qual_type_node(Context *c, QualType qt);
......@@ -107,8 +108,8 @@ static AstNode *make_type_node(Context *c, const Type *ty) {
107108 return simple_type_node(c, "bool");
108109 case BuiltinType::Char_U:
109110 case BuiltinType::UChar:
110 return simple_type_node(c, "u8");
111111 case BuiltinType::Char_S:
112 return simple_type_node(c, "u8");
112113 case BuiltinType::SChar:
113114 return simple_type_node(c, "i8");
114115 case BuiltinType::UShort:
......@@ -266,11 +267,18 @@ static AstNode *make_qual_type_node(Context *c, QualType qt) {
266267
267268static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {
268269 AstNode *node = create_node(c, NodeTypeFnProto);
270 buf_init_from_str(&node->data.fn_proto.name, decl_name(fn_decl));
271
272 auto fn_entry = c->fn_table.maybe_get(&node->data.fn_proto.name);
273 if (fn_entry) {
274 // we already saw this function
275 return;
276 }
277
269278 node->data.fn_proto.is_extern = true;
270279 node->data.fn_proto.visib_mod = c->visib_mod;
271280 node->data.fn_proto.directives = create_empty_directives(c);
272281 node->data.fn_proto.is_var_args = fn_decl->isVariadic();
273 buf_init_from_str(&node->data.fn_proto.name, decl_name(fn_decl));
274282
275283 int arg_count = fn_decl->getNumParams();
276284 bool all_ok = true;
......@@ -313,6 +321,7 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {
313321
314322 normalize_parent_ptrs(node);
315323
324 c->fn_table.put(&node->data.fn_proto.name, true);
316325 c->root->data.root.top_level_decls.append(node);
317326}
318327
......@@ -392,7 +401,9 @@ int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, ZigList<
392401 Context *c = &context;
393402 c->import = import;
394403 c->errors = errors;
395 c->type_table.init(64);
404 c->visib_mod = VisibModPub;
405 c->type_table.init(32);
406 c->fn_table.init(32);
396407
397408 char *ZIG_PARSEH_CFLAGS = getenv("ZIG_PARSEH_CFLAGS");
398409 if (ZIG_PARSEH_CFLAGS) {
......@@ -486,7 +497,6 @@ int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, ZigList<
486497 normalize_parent_ptrs(c->root);
487498
488499 import->root = c->root;
489 import->is_c_import = true;
490500
491501 return 0;
492502}
test/run_tests.cpp+9-2
......@@ -98,7 +98,11 @@ static void add_compiling_test_cases(void) {
9898 add_simple_case("hello world with libc", R"SOURCE(
9999#link("c")
100100export executable "test";
101extern fn puts(s: &const u8) -> c_int;
101
102c_import {
103 @c_include("stdio.h");
104}
105
102106export fn main(argc: c_int, argv: &&u8) -> c_int {
103107 puts(c"Hello, world!");
104108 return 0;
......@@ -481,7 +485,10 @@ pub fn main(args: [][]u8) -> %void {
481485 add_simple_case("number literals", R"SOURCE(
482486#link("c")
483487export executable "test";
484extern fn printf(__format: &const u8, ...) -> c_int;
488
489c_import {
490 @c_include("stdio.h");
491}
485492
486493export fn main(argc: c_int, argv: &&u8) -> c_int {
487494 printf(c"\n");