authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-02-01 02:00:25-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-02-01 02:00:25-07:00
logb3459f64e795118c4c12890ed0fec75638b74a2c
treed5730790d1b61f71a606e30023d68cc36071cce4
parent6b2e29c6ac58d5f4370828bfa0f54b83d1931a97

parseh understands macros which alias global fn ptr vars


5 files changed, 159 insertions(+), 18 deletions(-)

src/analyze.cpp+2
...@@ -29,6 +29,7 @@ static TypeTableEntry *analyze_block_expr(CodeGen *g, ImportTableEntry *import,...@@ -29,6 +29,7 @@ static TypeTableEntry *analyze_block_expr(CodeGen *g, ImportTableEntry *import,
29static TypeTableEntry *resolve_expr_const_val_as_void(CodeGen *g, AstNode *node);29static TypeTableEntry *resolve_expr_const_val_as_void(CodeGen *g, AstNode *node);
30static TypeTableEntry *resolve_expr_const_val_as_fn(CodeGen *g, AstNode *node, FnTableEntry *fn);30static TypeTableEntry *resolve_expr_const_val_as_fn(CodeGen *g, AstNode *node, FnTableEntry *fn);
31static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode *node);31static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode *node);
32static void analyze_top_level_decls_root(CodeGen *g, ImportTableEntry *import, AstNode *node);
3233
33static AstNode *first_executing_node(AstNode *node) {34static AstNode *first_executing_node(AstNode *node) {
34 switch (node->type) {35 switch (node->type) {
...@@ -1251,6 +1252,7 @@ static void resolve_c_import_decl(CodeGen *g, ImportTableEntry *parent_import, A...@@ -1251,6 +1252,7 @@ static void resolve_c_import_decl(CodeGen *g, ImportTableEntry *parent_import, A
1251 child_import->importers.append({parent_import, node});1252 child_import->importers.append({parent_import, node});
12521253
1253 detect_top_level_decl_deps(g, child_import, child_import->root);1254 detect_top_level_decl_deps(g, child_import, child_import->root);
1255 analyze_top_level_decls_root(g, child_import, child_import->root);
1254}1256}
12551257
1256static void satisfy_dep(CodeGen *g, AstNode *node) {1258static void satisfy_dep(CodeGen *g, AstNode *node) {
src/ast_render.cpp+53-7
...@@ -582,15 +582,34 @@ static void render_node(AstRender *ar, AstNode *node) {...@@ -582,15 +582,34 @@ static void render_node(AstRender *ar, AstNode *node) {
582 break;582 break;
583 }583 }
584 case NodeTypeFnDef:584 case NodeTypeFnDef:
585 zig_panic("TODO");585 for (int i = 0; i < node->data.fn_def.fn_proto->data.fn_proto.directives->length; i += 1) {
586 render_node(ar, node->data.fn_def.fn_proto->data.fn_proto.directives->at(i));
587 }
588 render_node(ar, node->data.fn_def.fn_proto);
589 fprintf(ar->f, " ");
590 render_node(ar, node->data.fn_def.body);
591 break;
586 case NodeTypeFnDecl:592 case NodeTypeFnDecl:
587 zig_panic("TODO");593 zig_panic("TODO");
588 case NodeTypeParamDecl:594 case NodeTypeParamDecl:
589 zig_panic("TODO");595 zig_panic("TODO");
590 case NodeTypeBlock:596 case NodeTypeBlock:
591 zig_panic("TODO");597 fprintf(ar->f, "{\n");
598 ar->indent += ar->indent_size;
599 for (int i = 0; i < node->data.block.statements.length; i += 1) {
600 AstNode *statement = node->data.block.statements.at(i);
601 print_indent(ar);
602 render_node(ar, statement);
603 }
604 ar->indent -= ar->indent_size;
605 fprintf(ar->f, "\n");
606 print_indent(ar);
607 fprintf(ar->f, "}");
608 break;
592 case NodeTypeDirective:609 case NodeTypeDirective:
593 zig_panic("TODO");610 fprintf(ar->f, "#%s(\"%s\")\n", buf_ptr(&node->data.directive.name),
611 buf_ptr(&node->data.directive.param));
612 break;
594 case NodeTypeReturnExpr:613 case NodeTypeReturnExpr:
595 zig_panic("TODO");614 zig_panic("TODO");
596 case NodeTypeVariableDeclaration:615 case NodeTypeVariableDeclaration:
...@@ -621,7 +640,12 @@ static void render_node(AstRender *ar, AstNode *node) {...@@ -621,7 +640,12 @@ static void render_node(AstRender *ar, AstNode *node) {
621 case NodeTypeErrorValueDecl:640 case NodeTypeErrorValueDecl:
622 zig_panic("TODO");641 zig_panic("TODO");
623 case NodeTypeBinOpExpr:642 case NodeTypeBinOpExpr:
624 zig_panic("TODO");643 fprintf(ar->f, "(");
644 render_node(ar, node->data.bin_op_expr.op1);
645 fprintf(ar->f, " %s ", bin_op_str(node->data.bin_op_expr.bin_op));
646 render_node(ar, node->data.bin_op_expr.op2);
647 fprintf(ar->f, ")");
648 break;
625 case NodeTypeUnwrapErrorExpr:649 case NodeTypeUnwrapErrorExpr:
626 zig_panic("TODO");650 zig_panic("TODO");
627 case NodeTypeNumberLiteral:651 case NodeTypeNumberLiteral:
...@@ -635,7 +659,11 @@ static void render_node(AstRender *ar, AstNode *node) {...@@ -635,7 +659,11 @@ static void render_node(AstRender *ar, AstNode *node) {
635 }659 }
636 break;660 break;
637 case NodeTypeStringLiteral:661 case NodeTypeStringLiteral:
638 zig_panic("TODO");662 if (node->data.string_literal.c) {
663 fprintf(ar->f, "c");
664 }
665 fprintf(ar->f, "\"%s\"", buf_ptr(&node->data.string_literal.buf));
666 break;
639 case NodeTypeCharLiteral:667 case NodeTypeCharLiteral:
640 {668 {
641 uint8_t c = node->data.char_literal.value;669 uint8_t c = node->data.char_literal.value;
...@@ -665,7 +693,20 @@ static void render_node(AstRender *ar, AstNode *node) {...@@ -665,7 +693,20 @@ static void render_node(AstRender *ar, AstNode *node) {
665 break;693 break;
666 }694 }
667 case NodeTypeFnCallExpr:695 case NodeTypeFnCallExpr:
668 zig_panic("TODO");696 if (node->data.fn_call_expr.is_builtin) {
697 fprintf(ar->f, "@");
698 }
699 render_node(ar, node->data.fn_call_expr.fn_ref_expr);
700 fprintf(ar->f, "(");
701 for (int i = 0; i < node->data.fn_call_expr.params.length; i += 1) {
702 AstNode *param = node->data.fn_call_expr.params.at(i);
703 if (i != 0) {
704 fprintf(ar->f, ", ");
705 }
706 render_node(ar, param);
707 }
708 fprintf(ar->f, ")");
709 break;
669 case NodeTypeArrayAccessExpr:710 case NodeTypeArrayAccessExpr:
670 zig_panic("TODO");711 zig_panic("TODO");
671 case NodeTypeSliceExpr:712 case NodeTypeSliceExpr:
...@@ -739,7 +780,12 @@ static void render_node(AstRender *ar, AstNode *node) {...@@ -739,7 +780,12 @@ static void render_node(AstRender *ar, AstNode *node) {
739 case NodeTypeStructField:780 case NodeTypeStructField:
740 zig_panic("TODO");781 zig_panic("TODO");
741 case NodeTypeContainerInitExpr:782 case NodeTypeContainerInitExpr:
742 zig_panic("TODO");783 fprintf(ar->f, "(");
784 render_node(ar, node->data.container_init_expr.type);
785 fprintf(ar->f, "){");
786 assert(node->data.container_init_expr.entries.length == 0);
787 fprintf(ar->f, "}");
788 break;
743 case NodeTypeStructValueField:789 case NodeTypeStructValueField:
744 zig_panic("TODO");790 zig_panic("TODO");
745 case NodeTypeArrayType:791 case NodeTypeArrayType:
src/codegen.cpp+3
...@@ -612,6 +612,8 @@ static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) {...@@ -612,6 +612,8 @@ static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) {
612 return LLVMBuildUnreachable(g->builder);612 return LLVMBuildUnreachable(g->builder);
613 } else if (first_arg_ret) {613 } else if (first_arg_ret) {
614 return node->data.fn_call_expr.tmp_ptr;614 return node->data.fn_call_expr.tmp_ptr;
615 } else if (src_return_type->size_in_bits == 0) {
616 return nullptr;
615 } else {617 } else {
616 return result;618 return result;
617 }619 }
...@@ -2767,6 +2769,7 @@ static void do_code_gen(CodeGen *g) {...@@ -2767,6 +2769,7 @@ static void do_code_gen(CodeGen *g) {
2767 }2769 }
27682770
2769 VariableTableEntry *variable = param_decl->data.param_decl.variable;2771 VariableTableEntry *variable = param_decl->data.param_decl.variable;
2772 assert(variable);
27702773
2771 LLVMZigDILocation *debug_loc = LLVMZigGetDebugLoc(param_decl->line + 1, param_decl->column + 1,2774 LLVMZigDILocation *debug_loc = LLVMZigGetDebugLoc(param_decl->line + 1, param_decl->column + 1,
2772 fn_def_node->data.fn_def.block_context->di_scope);2775 fn_def_node->data.fn_def.block_context->di_scope);
src/parseh.cpp+93
...@@ -51,6 +51,7 @@ struct Context {...@@ -51,6 +51,7 @@ struct Context {
51 AstNode *source_node;51 AstNode *source_node;
5252
53 CodeGen *codegen;53 CodeGen *codegen;
54 bool transform_extern_fn_ptr;
54};55};
5556
56static TypeTableEntry *resolve_qual_type_with_table(Context *c, QualType qt, const Decl *decl,57static TypeTableEntry *resolve_qual_type_with_table(Context *c, QualType qt, const Decl *decl,
...@@ -196,6 +197,13 @@ static AstNode *create_num_lit_signed(Context *c, int64_t x) {...@@ -196,6 +197,13 @@ static AstNode *create_num_lit_signed(Context *c, int64_t x) {
196 return create_prefix_node(c, PrefixOpNegation, num_lit_node);197 return create_prefix_node(c, PrefixOpNegation, num_lit_node);
197}198}
198199
200static AstNode *create_directive_node(Context *c, const char *name, const char *value) {
201 AstNode *node = create_node(c, NodeTypeDirective);
202 buf_init_from_str(&node->data.directive.name, name);
203 buf_init_from_str(&node->data.directive.param, value);
204 return node;
205}
206
199static AstNode *create_type_decl_node(Context *c, const char *name, AstNode *child_type_node) {207static AstNode *create_type_decl_node(Context *c, const char *name, AstNode *child_type_node) {
200 AstNode *node = create_node(c, NodeTypeTypeDecl);208 AstNode *node = create_node(c, NodeTypeTypeDecl);
201 buf_init_from_str(&node->data.type_decl.symbol, name);209 buf_init_from_str(&node->data.type_decl.symbol, name);
...@@ -213,6 +221,80 @@ static AstNode *make_type_node(Context *c, TypeTableEntry *type_entry) {...@@ -213,6 +221,80 @@ static AstNode *make_type_node(Context *c, TypeTableEntry *type_entry) {
213 return node;221 return node;
214}222}
215223
224static AstNode *create_fn_proto_node(Context *c, Buf *name, TypeTableEntry *fn_type) {
225 assert(fn_type->id == TypeTableEntryIdFn);
226 AstNode *node = create_node(c, NodeTypeFnProto);
227 node->data.fn_proto.directives = create_empty_directives(c);
228 node->data.fn_proto.directives->append(create_directive_node(c, "attribute", "inline"));
229 node->data.fn_proto.visib_mod = c->visib_mod;
230 buf_init_from_buf(&node->data.fn_proto.name, name);
231 node->data.fn_proto.return_type = make_type_node(c, fn_type->data.fn.fn_type_id.return_type);
232
233 for (int i = 0; i < fn_type->data.fn.fn_type_id.param_count; i += 1) {
234 FnTypeParamInfo *info = &fn_type->data.fn.fn_type_id.param_info[i];
235 Buf *name = buf_sprintf("arg_%d", i);
236 node->data.fn_proto.params.append(create_param_decl_node(c, buf_ptr(name),
237 make_type_node(c, info->type), info->is_noalias));
238 }
239
240 normalize_parent_ptrs(node);
241 return node;
242}
243
244static AstNode *create_one_statement_block(Context *c, AstNode *statement) {
245 AstNode *node = create_node(c, NodeTypeBlock);
246 node->data.block.statements.append(statement);
247
248 normalize_parent_ptrs(node);
249 return node;
250}
251
252static AstNode *create_container_init_node(Context *c, AstNode *type_node) {
253 AstNode *node = create_node(c, NodeTypeContainerInitExpr);
254 node->data.container_init_expr.kind = ContainerInitKindArray;
255 node->data.container_init_expr.type = type_node;
256
257 normalize_parent_ptrs(node);
258 return node;
259}
260
261static AstNode *create_bin_op_node(Context *c, AstNode *lhs, BinOpType op, AstNode *rhs) {
262 AstNode *node = create_node(c, NodeTypeBinOpExpr);
263 node->data.bin_op_expr.op1 = lhs;
264 node->data.bin_op_expr.bin_op = op;
265 node->data.bin_op_expr.op2 = rhs;
266
267 normalize_parent_ptrs(node);
268 return node;
269}
270
271static AstNode *create_inline_fn_node(Context *c, Buf *fn_name, Buf *var_name, TypeTableEntry *fn_type) {
272 AstNode *node = create_node(c, NodeTypeFnDef);
273 node->data.fn_def.fn_proto = create_fn_proto_node(c, fn_name, fn_type);
274
275 AstNode *unreach_type_node = make_type_node(c, c->codegen->builtin_types.entry_unreachable);
276 AstNode *unreach_node = create_container_init_node(c, unreach_type_node);
277 AstNode *unwrap_node = create_bin_op_node(c, create_symbol_node(c, buf_ptr(var_name)),
278 BinOpTypeUnwrapMaybe, unreach_node);
279
280 AstNode *fn_call_node = create_node(c, NodeTypeFnCallExpr);
281 fn_call_node->data.fn_call_expr.fn_ref_expr = unwrap_node;
282 for (int i = 0; i < fn_type->data.fn.fn_type_id.param_count; i += 1) {
283 AstNode *decl_node = node->data.fn_def.fn_proto->data.fn_proto.params.at(i);
284 Buf *param_name = &decl_node->data.param_decl.name;
285 fn_call_node->data.fn_call_expr.params.append(create_symbol_node(c, buf_ptr(param_name)));
286 }
287
288 normalize_parent_ptrs(fn_call_node);
289
290 node->data.fn_def.body = create_one_statement_block(c, fn_call_node);
291
292 normalize_parent_ptrs(node);
293 return node;
294}
295
296
297
216static const char *decl_name(const Decl *decl) {298static const char *decl_name(const Decl *decl) {
217 const NamedDecl *named_decl = static_cast<const NamedDecl *>(decl);299 const NamedDecl *named_decl = static_cast<const NamedDecl *>(decl);
218 return (const char *)named_decl->getName().bytes_begin();300 return (const char *)named_decl->getName().bytes_begin();
...@@ -1257,6 +1339,17 @@ static void process_symbol_macros(Context *c) {...@@ -1257,6 +1339,17 @@ static void process_symbol_macros(Context *c) {
1257 AstNode *var_node = create_var_decl_node(c, buf_ptr(ms.name),1339 AstNode *var_node = create_var_decl_node(c, buf_ptr(ms.name),
1258 create_symbol_node(c, buf_ptr(ms.value)));1340 create_symbol_node(c, buf_ptr(ms.value)));
1259 c->macro_table.put(ms.name, var_node);1341 c->macro_table.put(ms.name, var_node);
1342 } else if (c->transform_extern_fn_ptr || true) { // TODO take off the || true
1343 if (auto entry = c->global_value_table.maybe_get(ms.value)) {
1344 TypeTableEntry *maybe_type = entry->value.type;
1345 if (maybe_type->id == TypeTableEntryIdMaybe) {
1346 TypeTableEntry *fn_type = maybe_type->data.maybe.child_type;
1347 if (fn_type->id == TypeTableEntryIdFn) {
1348 AstNode *fn_node = create_inline_fn_node(c, ms.name, ms.value, fn_type);
1349 c->macro_table.put(ms.name, fn_node);
1350 }
1351 }
1352 }
1260 }1353 }
1261 }1354 }
1262}1355}
test/run_tests.cpp+8-11
...@@ -2109,18 +2109,15 @@ Foo fun(Foo *a);...@@ -2109,18 +2109,15 @@ Foo fun(Foo *a);
2109 "pub const Foo = c_void;",2109 "pub const Foo = c_void;",
2110 "pub extern fn fun(a: ?&c_void);");2110 "pub extern fn fun(a: ?&c_void);");
21112111
2112 add_parseh_case("ignore #define for non-const", R"SOURCE(2112 add_parseh_case("generate inline func for #define global extern fn", R"SOURCE(
2113struct Foo {
2114 int x;
2115};
2116extern void (*fn_ptr)(void);2113extern void (*fn_ptr)(void);
2117#define Foo fn_ptr2114#define foo fn_ptr
2118 )SOURCE", 3,2115 )SOURCE", 2,
2119 "pub type c_void = u8;",2116 "pub extern var fn_ptr: ?extern fn();",
2120 "pub const Foo = struct_Foo;",2117 R"SOURCE(#attribute("inline")
2121 R"OUTPUT(export struct struct_Foo {2118pub fn foo() {
2122 x: c_int,2119 (fn_ptr ?? (unreachable){})()
2123})OUTPUT");2120})SOURCE");
2124}2121}
21252122
2126static void print_compiler_invocation(TestCase *test_case) {2123static void print_compiler_invocation(TestCase *test_case) {