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 @@...@@ -1,7 +1,9 @@
1#link("c")1#link("c")
2export executable "hello";2export executable "hello";
33
4extern fn printf(__format: &const u8, ...) -> c_int;4c_import {
5 @c_include("stdio.h");
6}
57
6export fn main(argc: c_int, argv: &&u8) -> c_int {8export fn main(argc: c_int, argv: &&u8) -> c_int {
7 printf(c"Hello, world!\n");9 printf(c"Hello, world!\n");
src/all_types.hpp+1-1
...@@ -894,7 +894,7 @@ struct ImportTableEntry {...@@ -894,7 +894,7 @@ struct ImportTableEntry {
894 ZigList<int> *line_offsets;894 ZigList<int> *line_offsets;
895 BlockContext *block_context;895 BlockContext *block_context;
896 ZigList<ImporterInfo> importers;896 ZigList<ImporterInfo> importers;
897 bool is_c_import;897 AstNode *c_import_node;
898898
899 // reminder: hash tables must be initialized before use899 // reminder: hash tables must be initialized before use
900 HashMap<Buf *, FnTableEntry *, buf_hash, buf_eql_buf> fn_table;900 HashMap<Buf *, FnTableEntry *, buf_hash, buf_eql_buf> fn_table;
src/analyze.cpp+40-11
...@@ -12,6 +12,7 @@...@@ -12,6 +12,7 @@
12#include "os.hpp"12#include "os.hpp"
13#include "parseh.hpp"13#include "parseh.hpp"
14#include "config.h"14#include "config.h"
15#include "ast_render.hpp"
1516
16static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, BlockContext *context,17static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, BlockContext *context,
17 TypeTableEntry *expected_type, AstNode *node);18 TypeTableEntry *expected_type, AstNode *node);
...@@ -26,6 +27,7 @@ static TypeTableEntry *analyze_error_literal_expr(CodeGen *g, ImportTableEntry *...@@ -26,6 +27,7 @@ static TypeTableEntry *analyze_error_literal_expr(CodeGen *g, ImportTableEntry *
26static TypeTableEntry *analyze_block_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,27static TypeTableEntry *analyze_block_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
27 TypeTableEntry *expected_type, AstNode *node);28 TypeTableEntry *expected_type, AstNode *node);
28static TypeTableEntry *resolve_expr_const_val_as_void(CodeGen *g, AstNode *node);29static 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
30static AstNode *first_executing_node(AstNode *node) {32static AstNode *first_executing_node(AstNode *node) {
31 switch (node->type) {33 switch (node->type) {
...@@ -87,6 +89,8 @@ static AstNode *first_executing_node(AstNode *node) {...@@ -87,6 +89,8 @@ static AstNode *first_executing_node(AstNode *node) {
87}89}
8890
89ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg) {91ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg) {
92 assert(!node->owner->c_import_node);
93
90 ErrorMsg *err = err_msg_create_with_line(node->owner->path, node->line, node->column,94 ErrorMsg *err = err_msg_create_with_line(node->owner->path, node->line, node->column,
91 node->owner->source_code, node->owner->line_offsets, msg);95 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...@@ -1056,11 +1060,15 @@ static void resolve_c_import_decl(CodeGen *g, ImportTableEntry *parent_import, A
10561060
1057 find_libc_path(g);1061 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
1060 ZigList<ErrorMsg *> errors = {0};1068 ZigList<ErrorMsg *> errors = {0};
10611069
1062 int err;1070 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,
1064 buf_ptr(g->libc_include_path))))1072 buf_ptr(g->libc_include_path))))
1065 {1073 {
1066 zig_panic("unable to parse h file: %s\n", err_str(err));1074 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...@@ -1075,7 +1083,24 @@ static void resolve_c_import_decl(CodeGen *g, ImportTableEntry *parent_import, A
1075 return;1083 return;
1076 }1084 }
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 }
1079}1104}
10801105
1081static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode *node) {1106static 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...@@ -1085,7 +1110,7 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode
1085 break;1110 break;
1086 case NodeTypeRootExportDecl:1111 case NodeTypeRootExportDecl:
1087 // handled earlier1112 // handled earlier
1088 break;1113 return;
1089 case NodeTypeStructDecl:1114 case NodeTypeStructDecl:
1090 {1115 {
1091 TypeTableEntry *type_entry = node->data.struct_decl.type_entry;1116 TypeTableEntry *type_entry = node->data.struct_decl.type_entry;
...@@ -1115,7 +1140,7 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode...@@ -1115,7 +1140,7 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode
1115 break;1140 break;
1116 case NodeTypeImport:1141 case NodeTypeImport:
1117 // nothing to do here1142 // nothing to do here
1118 break;1143 return;
1119 case NodeTypeCImport:1144 case NodeTypeCImport:
1120 resolve_c_import_decl(g, import, node);1145 resolve_c_import_decl(g, import, node);
1121 break;1146 break;
...@@ -1159,6 +1184,9 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode...@@ -1159,6 +1184,9 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode
1159 case NodeTypeErrorType:1184 case NodeTypeErrorType:
1160 zig_unreachable();1185 zig_unreachable();
1161 }1186 }
1187
1188
1189 satisfy_dep(g, node);
1162}1190}
11631191
1164static FnTableEntry *get_context_fn_entry(BlockContext *context) {1192static FnTableEntry *get_context_fn_entry(BlockContext *context) {
...@@ -4512,6 +4540,12 @@ static TypeTableEntryId container_to_type(ContainerKind kind) {...@@ -4512,6 +4540,12 @@ static TypeTableEntryId container_to_type(ContainerKind kind) {
45124540
4513static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode *node) {4541static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode *node) {
4514 switch (node->type) {4542 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;
4515 case NodeTypeStructDecl:4549 case NodeTypeStructDecl:
4516 {4550 {
4517 Buf *name = &node->data.struct_decl.name;4551 Buf *name = &node->data.struct_decl.name;
...@@ -4664,7 +4698,6 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast...@@ -4664,7 +4698,6 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast
4664 case NodeTypeParamDecl:4698 case NodeTypeParamDecl:
4665 case NodeTypeFnDecl:4699 case NodeTypeFnDecl:
4666 case NodeTypeReturnExpr:4700 case NodeTypeReturnExpr:
4667 case NodeTypeRoot:
4668 case NodeTypeBlock:4701 case NodeTypeBlock:
4669 case NodeTypeBinOpExpr:4702 case NodeTypeBinOpExpr:
4670 case NodeTypeUnwrapErrorExpr:4703 case NodeTypeUnwrapErrorExpr:
...@@ -4732,7 +4765,6 @@ static void recursive_resolve_decl(CodeGen *g, ImportTableEntry *import, AstNode...@@ -4732,7 +4765,6 @@ static void recursive_resolve_decl(CodeGen *g, ImportTableEntry *import, AstNode
4732 }4765 }
47334766
4734 resolve_top_level_decl(g, import, node);4767 resolve_top_level_decl(g, import, node);
4735 g->unresolved_top_level_decls.remove(get_resolved_top_level_decl(node)->name);
4736}4768}
47374769
4738static void resolve_top_level_declarations_root(CodeGen *g, ImportTableEntry *import, AstNode *node) {4770static void resolve_top_level_declarations_root(CodeGen *g, ImportTableEntry *import, AstNode *node) {
...@@ -4823,10 +4855,7 @@ void semantic_analyze(CodeGen *g) {...@@ -4823,10 +4855,7 @@ void semantic_analyze(CodeGen *g) {
48234855
4824 ImportTableEntry *import = entry->value;4856 ImportTableEntry *import = entry->value;
48254857
4826 for (int i = 0; i < import->root->data.root.top_level_decls.length; i += 1) {4858 detect_top_level_decl_deps(g, import, import->root);
4827 AstNode *child = import->root->data.root.top_level_decls.at(i);
4828 detect_top_level_decl_deps(g, import, child);
4829 }
4830 }4859 }
4831 }4860 }
48324861
src/hash_map.hpp+6
...@@ -72,6 +72,12 @@ public:...@@ -72,6 +72,12 @@ public:
72 return internal_get(key);72 return internal_get(key);
73 }73 }
7474
75 void maybe_remove(const K &key) {
76 if (maybe_get(key)) {
77 remove(key);
78 }
79 }
80
75 void remove(const K &key) {81 void remove(const K &key) {
76 _modification_count += 1;82 _modification_count += 1;
77 int start_index = key_to_index(key);83 int start_index = key_to_index(key);
src/parseh.cpp+14-4
...@@ -27,6 +27,7 @@ struct Context {...@@ -27,6 +27,7 @@ struct Context {
27 AstNode *c_void_decl_node;27 AstNode *c_void_decl_node;
28 AstNode *root;28 AstNode *root;
29 HashMap<Buf *, bool, buf_hash, buf_eql_buf> type_table;29 HashMap<Buf *, bool, buf_hash, buf_eql_buf> type_table;
30 HashMap<Buf *, bool, buf_hash, buf_eql_buf> fn_table;
30};31};
3132
32static AstNode *make_qual_type_node(Context *c, QualType qt);33static AstNode *make_qual_type_node(Context *c, QualType qt);
...@@ -107,8 +108,8 @@ static AstNode *make_type_node(Context *c, const Type *ty) {...@@ -107,8 +108,8 @@ static AstNode *make_type_node(Context *c, const Type *ty) {
107 return simple_type_node(c, "bool");108 return simple_type_node(c, "bool");
108 case BuiltinType::Char_U:109 case BuiltinType::Char_U:
109 case BuiltinType::UChar:110 case BuiltinType::UChar:
110 return simple_type_node(c, "u8");
111 case BuiltinType::Char_S:111 case BuiltinType::Char_S:
112 return simple_type_node(c, "u8");
112 case BuiltinType::SChar:113 case BuiltinType::SChar:
113 return simple_type_node(c, "i8");114 return simple_type_node(c, "i8");
114 case BuiltinType::UShort:115 case BuiltinType::UShort:
...@@ -266,11 +267,18 @@ static AstNode *make_qual_type_node(Context *c, QualType qt) {...@@ -266,11 +267,18 @@ static AstNode *make_qual_type_node(Context *c, QualType qt) {
266267
267static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {268static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {
268 AstNode *node = create_node(c, NodeTypeFnProto);269 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
269 node->data.fn_proto.is_extern = true;278 node->data.fn_proto.is_extern = true;
270 node->data.fn_proto.visib_mod = c->visib_mod;279 node->data.fn_proto.visib_mod = c->visib_mod;
271 node->data.fn_proto.directives = create_empty_directives(c);280 node->data.fn_proto.directives = create_empty_directives(c);
272 node->data.fn_proto.is_var_args = fn_decl->isVariadic();281 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
275 int arg_count = fn_decl->getNumParams();283 int arg_count = fn_decl->getNumParams();
276 bool all_ok = true;284 bool all_ok = true;
...@@ -313,6 +321,7 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {...@@ -313,6 +321,7 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {
313321
314 normalize_parent_ptrs(node);322 normalize_parent_ptrs(node);
315323
324 c->fn_table.put(&node->data.fn_proto.name, true);
316 c->root->data.root.top_level_decls.append(node);325 c->root->data.root.top_level_decls.append(node);
317}326}
318327
...@@ -392,7 +401,9 @@ int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, ZigList<...@@ -392,7 +401,9 @@ int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, ZigList<
392 Context *c = &context;401 Context *c = &context;
393 c->import = import;402 c->import = import;
394 c->errors = errors;403 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
397 char *ZIG_PARSEH_CFLAGS = getenv("ZIG_PARSEH_CFLAGS");408 char *ZIG_PARSEH_CFLAGS = getenv("ZIG_PARSEH_CFLAGS");
398 if (ZIG_PARSEH_CFLAGS) {409 if (ZIG_PARSEH_CFLAGS) {
...@@ -486,7 +497,6 @@ int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, ZigList<...@@ -486,7 +497,6 @@ int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, ZigList<
486 normalize_parent_ptrs(c->root);497 normalize_parent_ptrs(c->root);
487498
488 import->root = c->root;499 import->root = c->root;
489 import->is_c_import = true;
490500
491 return 0;501 return 0;
492}502}
test/run_tests.cpp+9-2
...@@ -98,7 +98,11 @@ static void add_compiling_test_cases(void) {...@@ -98,7 +98,11 @@ static void add_compiling_test_cases(void) {
98 add_simple_case("hello world with libc", R"SOURCE(98 add_simple_case("hello world with libc", R"SOURCE(
99#link("c")99#link("c")
100export executable "test";100export executable "test";
101extern fn puts(s: &const u8) -> c_int;101
102c_import {
103 @c_include("stdio.h");
104}
105
102export fn main(argc: c_int, argv: &&u8) -> c_int {106export fn main(argc: c_int, argv: &&u8) -> c_int {
103 puts(c"Hello, world!");107 puts(c"Hello, world!");
104 return 0;108 return 0;
...@@ -481,7 +485,10 @@ pub fn main(args: [][]u8) -> %void {...@@ -481,7 +485,10 @@ pub fn main(args: [][]u8) -> %void {
481 add_simple_case("number literals", R"SOURCE(485 add_simple_case("number literals", R"SOURCE(
482#link("c")486#link("c")
483export executable "test";487export executable "test";
484extern fn printf(__format: &const u8, ...) -> c_int;488
489c_import {
490 @c_include("stdio.h");
491}
485492
486export fn main(argc: c_int, argv: &&u8) -> c_int {493export fn main(argc: c_int, argv: &&u8) -> c_int {
487 printf(c"\n");494 printf(c"\n");