authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2015-12-15 21:48:41-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2015-12-15 21:48:41-07:00
log4d45d14b557365bfb5b9059347ec144784d481b7
treee5d59f94eeaf9847bb3a112ff74bdbd25f4362b8
parentaa56f016f73063371431b8b2587538c79af97bd9

use realpath to avoid duplicate imports


5 files changed, 126 insertions(+), 50 deletions(-)

example/structs/structs.zig+20
...@@ -17,6 +17,8 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {...@@ -17,6 +17,8 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
17 print_str("BAD\n");17 print_str("BAD\n");
18 }18 }
1919
20 test_point_to_self();
21
20 print_str("OK\n");22 print_str("OK\n");
21 return 0;23 return 0;
22}24}
...@@ -27,6 +29,11 @@ struct Foo {...@@ -27,6 +29,11 @@ struct Foo {
27 c : f32,29 c : f32,
28}30}
2931
32struct Node {
33 val: i32,
34 next: &Node,
35}
36
30fn test_foo(foo : Foo) {37fn test_foo(foo : Foo) {
31 if !foo.b {38 if !foo.b {
32 print_str("BAD\n");39 print_str("BAD\n");
...@@ -36,3 +43,16 @@ fn test_foo(foo : Foo) {...@@ -36,3 +43,16 @@ fn test_foo(foo : Foo) {
36fn modify_foo(foo : &Foo) {43fn modify_foo(foo : &Foo) {
37 foo.c = 100;44 foo.c = 100;
38}45}
46
47fn test_point_to_self() {
48 var root : Node;
49 root.val = 1;
50
51 var node : Node;
52 node.next = &root;
53 node.val = 2;
54
55 if node.next.val != 1 {
56 print_str("BAD\n");
57 }
58}
src/codegen.cpp+58-25
...@@ -209,10 +209,17 @@ static LLVMValueRef gen_array_ptr(CodeGen *g, AstNode *node) {...@@ -209,10 +209,17 @@ static LLVMValueRef gen_array_ptr(CodeGen *g, AstNode *node) {
209static LLVMValueRef gen_field_ptr(CodeGen *g, AstNode *node, TypeTableEntry **out_type_entry) {209static LLVMValueRef gen_field_ptr(CodeGen *g, AstNode *node, TypeTableEntry **out_type_entry) {
210 assert(node->type == NodeTypeFieldAccessExpr);210 assert(node->type == NodeTypeFieldAccessExpr);
211211
212 //TypeTableEntry *struct_type = get_expr_type(node->data.field_access_expr.struct_expr);
212 LLVMValueRef struct_ptr = gen_expr(g, node->data.field_access_expr.struct_expr);213 LLVMValueRef struct_ptr = gen_expr(g, node->data.field_access_expr.struct_expr);
213
214 assert(struct_ptr);214 assert(struct_ptr);
215215
216 /*
217 if (struct_type->id == TypeTableEntryIdPointer) {
218 add_debug_source_node(g, node);
219 struct_ptr = LLVMBuildLoad(g->builder, struct_ptr, "");
220 }
221 */
222
216 FieldAccessNode *codegen_field_access = &node->codegen_node->data.field_access_node;223 FieldAccessNode *codegen_field_access = &node->codegen_node->data.field_access_node;
217224
218 assert(codegen_field_access->field_index >= 0);225 assert(codegen_field_access->field_index >= 0);
...@@ -244,12 +251,12 @@ static LLVMValueRef gen_field_access_expr(CodeGen *g, AstNode *node) {...@@ -244,12 +251,12 @@ static LLVMValueRef gen_field_access_expr(CodeGen *g, AstNode *node) {
244 } else {251 } else {
245 zig_panic("gen_field_access_expr bad array field");252 zig_panic("gen_field_access_expr bad array field");
246 }253 }
247 } else if (struct_type->id == TypeTableEntryIdStruct) {254 } else if (struct_type->id == TypeTableEntryIdStruct || (struct_type->id == TypeTableEntryIdPointer &&
255 struct_type->data.pointer.child_type->id == TypeTableEntryIdStruct))
256 {
248 TypeTableEntry *type_entry;257 TypeTableEntry *type_entry;
249 LLVMValueRef ptr = gen_field_ptr(g, node, &type_entry);258 LLVMValueRef ptr = gen_field_ptr(g, node, &type_entry);
250 return LLVMBuildLoad(g->builder, ptr, "");259 return LLVMBuildLoad(g->builder, ptr, "");
251 } else if (struct_type->id == TypeTableEntryIdPointer) {
252 zig_panic("TODO struct pointer access");
253 } else {260 } else {
254 zig_panic("gen_field_access_expr bad struct type");261 zig_panic("gen_field_access_expr bad struct type");
255 }262 }
...@@ -1611,7 +1618,9 @@ static bool directives_contains_link_libc(ZigList<AstNode*> *directives) {...@@ -1611,7 +1618,9 @@ static bool directives_contains_link_libc(ZigList<AstNode*> *directives) {
1611 return false;1618 return false;
1612}1619}
16131620
1614static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *src_dirname, Buf *src_basename, Buf *source_code) {1621static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *abs_full_path,
1622 Buf *src_dirname, Buf *src_basename, Buf *source_code)
1623{
1615 int err;1624 int err;
1616 Buf *full_path = buf_alloc();1625 Buf *full_path = buf_alloc();
1617 os_path_join(src_dirname, src_basename, full_path);1626 os_path_join(src_dirname, src_basename, full_path);
...@@ -1662,7 +1671,7 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *src_dirname, Buf *src...@@ -1662,7 +1671,7 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *src_dirname, Buf *src
1662 }1671 }
16631672
1664 import_entry->di_file = LLVMZigCreateFile(g->dbuilder, buf_ptr(src_basename), buf_ptr(src_dirname));1673 import_entry->di_file = LLVMZigCreateFile(g->dbuilder, buf_ptr(src_basename), buf_ptr(src_dirname));
1665 g->import_table.put(full_path, import_entry);1674 g->import_table.put(abs_full_path, import_entry);
16661675
1667 import_entry->block_context = new_block_context(import_entry->root, nullptr);1676 import_entry->block_context = new_block_context(import_entry->root, nullptr);
1668 import_entry->block_context->di_scope = LLVMZigFileToScope(import_entry->di_file);1677 import_entry->block_context->di_scope = LLVMZigFileToScope(import_entry->di_file);
...@@ -1674,17 +1683,30 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *src_dirname, Buf *src...@@ -1674,17 +1683,30 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *src_dirname, Buf *src
16741683
1675 if (top_level_decl->type == NodeTypeUse) {1684 if (top_level_decl->type == NodeTypeUse) {
1676 Buf *import_target_path = &top_level_decl->data.use.path;1685 Buf *import_target_path = &top_level_decl->data.use.path;
1677 auto entry = g->import_table.maybe_get(import_target_path);1686 Buf full_path = BUF_INIT;
1678 if (!entry) {1687 Buf *import_code = buf_alloc();
1679 Buf full_path = BUF_INIT;1688 bool found_it = false;
1680 Buf *import_code = buf_alloc();1689
1681 bool found_it = false;1690 for (int path_i = 0; path_i < g->lib_search_paths.length; path_i += 1) {
16821691 Buf *search_path = g->lib_search_paths.at(path_i);
1683 for (int path_i = 0; path_i < g->lib_search_paths.length; path_i += 1) {1692 os_path_join(search_path, import_target_path, &full_path);
1684 Buf *search_path = g->lib_search_paths.at(path_i);1693
1685 os_path_join(search_path, import_target_path, &full_path);1694 Buf *abs_full_path = buf_alloc();
1695 if ((err = os_path_real(&full_path, abs_full_path))) {
1696 if (err == ErrorFileNotFound) {
1697 continue;
1698 } else {
1699 add_node_error(g, top_level_decl,
1700 buf_sprintf("unable to open '%s': %s", buf_ptr(&full_path), err_str(err)));
1701 goto done_looking_at_imports;
1702 }
1703 }
16861704
1687 if ((err = os_fetch_file_path(&full_path, import_code))) {1705 auto entry = g->import_table.maybe_get(abs_full_path);
1706 if (entry) {
1707 found_it = true;
1708 } else {
1709 if ((err = os_fetch_file_path(abs_full_path, import_code))) {
1688 if (err == ErrorFileNotFound) {1710 if (err == ErrorFileNotFound) {
1689 continue;1711 continue;
1690 } else {1712 } else {
...@@ -1693,14 +1715,14 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *src_dirname, Buf *src...@@ -1693,14 +1715,14 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *src_dirname, Buf *src
1693 goto done_looking_at_imports;1715 goto done_looking_at_imports;
1694 }1716 }
1695 }1717 }
1696 codegen_add_code(g, search_path, &top_level_decl->data.use.path, import_code);1718 codegen_add_code(g, abs_full_path, search_path, &top_level_decl->data.use.path, import_code);
1697 found_it = true;1719 found_it = true;
1698 break;
1699 }
1700 if (!found_it) {
1701 add_node_error(g, top_level_decl,
1702 buf_sprintf("unable to find '%s'", buf_ptr(import_target_path)));
1703 }1720 }
1721 break;
1722 }
1723 if (!found_it) {
1724 add_node_error(g, top_level_decl,
1725 buf_sprintf("unable to find '%s'", buf_ptr(import_target_path)));
1704 }1726 }
1705 } else if (top_level_decl->type == NodeTypeFnDef) {1727 } else if (top_level_decl->type == NodeTypeFnDef) {
1706 AstNode *proto_node = top_level_decl->data.fn_def.fn_proto;1728 AstNode *proto_node = top_level_decl->data.fn_def.fn_proto;
...@@ -1727,20 +1749,30 @@ void codegen_add_root_code(CodeGen *g, Buf *src_dir, Buf *src_basename, Buf *sou...@@ -1727,20 +1749,30 @@ void codegen_add_root_code(CodeGen *g, Buf *src_dir, Buf *src_basename, Buf *sou
1727 os_path_join(src_dir, src_basename, &source_path);1749 os_path_join(src_dir, src_basename, &source_path);
1728 init(g, &source_path);1750 init(g, &source_path);
17291751
1730 g->root_import = codegen_add_code(g, src_dir, src_basename, source_code);1752 Buf *abs_full_path = buf_alloc();
1753 int err;
1754 if ((err = os_path_real(&source_path, abs_full_path))) {
1755 zig_panic("unable to open '%s': %s", buf_ptr(&source_path), err_str(err));
1756 }
1757
1758 g->root_import = codegen_add_code(g, abs_full_path, src_dir, src_basename, source_code);
17311759
1732 if (g->have_exported_main && !g->link_libc && g->out_type != OutTypeLib) {1760 if (g->have_exported_main && !g->link_libc && g->out_type != OutTypeLib) {
1733 Buf *bootstrap_dir = buf_create_from_str(ZIG_STD_DIR);1761 Buf *bootstrap_dir = buf_create_from_str(ZIG_STD_DIR);
1734 Buf *bootstrap_basename = buf_create_from_str("bootstrap.zig");1762 Buf *bootstrap_basename = buf_create_from_str("bootstrap.zig");
1735 Buf path_to_bootstrap_src = BUF_INIT;1763 Buf path_to_bootstrap_src = BUF_INIT;
1736 os_path_join(bootstrap_dir, bootstrap_basename, &path_to_bootstrap_src);1764 os_path_join(bootstrap_dir, bootstrap_basename, &path_to_bootstrap_src);
1765 Buf *abs_full_path = buf_alloc();
1766 if ((err = os_path_real(&path_to_bootstrap_src, abs_full_path))) {
1767 zig_panic("unable to open '%s': %s", buf_ptr(&path_to_bootstrap_src), err_str(err));
1768 }
1737 Buf *import_code = buf_alloc();1769 Buf *import_code = buf_alloc();
1738 int err;1770 int err;
1739 if ((err = os_fetch_file_path(&path_to_bootstrap_src, import_code))) {1771 if ((err = os_fetch_file_path(abs_full_path, import_code))) {
1740 zig_panic("unable to open '%s': %s", buf_ptr(&path_to_bootstrap_src), err_str(err));1772 zig_panic("unable to open '%s': %s", buf_ptr(&path_to_bootstrap_src), err_str(err));
1741 }1773 }
17421774
1743 codegen_add_code(g, bootstrap_dir, bootstrap_basename, import_code);1775 codegen_add_code(g, abs_full_path, bootstrap_dir, bootstrap_basename, import_code);
1744 }1776 }
17451777
1746 if (g->verbose) {1778 if (g->verbose) {
...@@ -1963,6 +1995,7 @@ void codegen_link(CodeGen *g, const char *out_file) {...@@ -1963,6 +1995,7 @@ void codegen_link(CodeGen *g, const char *out_file) {
1963 crt1o = "Scrt1.o";1995 crt1o = "Scrt1.o";
1964 }1996 }
19651997
1998 // TODO don't pass this parameter unless linking with libc
1966 char *ZIG_NATIVE_DYNAMIC_LINKER = getenv("ZIG_NATIVE_DYNAMIC_LINKER");1999 char *ZIG_NATIVE_DYNAMIC_LINKER = getenv("ZIG_NATIVE_DYNAMIC_LINKER");
1967 if (g->is_native_target && ZIG_NATIVE_DYNAMIC_LINKER) {2000 if (g->is_native_target && ZIG_NATIVE_DYNAMIC_LINKER) {
1968 if (ZIG_NATIVE_DYNAMIC_LINKER[0] != 0) {2001 if (ZIG_NATIVE_DYNAMIC_LINKER[0] != 0) {
src/os.cpp+19
...@@ -83,6 +83,25 @@ void os_path_join(Buf *dirname, Buf *basename, Buf *out_full_path) {...@@ -83,6 +83,25 @@ void os_path_join(Buf *dirname, Buf *basename, Buf *out_full_path) {
83 buf_append_buf(out_full_path, basename);83 buf_append_buf(out_full_path, basename);
84}84}
8585
86int os_path_real(Buf *rel_path, Buf *out_abs_path) {
87 buf_resize(out_abs_path, PATH_MAX + 1);
88 char *result = realpath(buf_ptr(rel_path), buf_ptr(out_abs_path));
89 if (!result) {
90 int err = errno;
91 if (err == EACCES) {
92 return ErrorAccess;
93 } else if (err == ENOENT) {
94 return ErrorFileNotFound;
95 } else if (err == ENOMEM) {
96 return ErrorNoMem;
97 } else {
98 return ErrorFileSystem;
99 }
100 }
101 buf_resize(out_abs_path, strlen(buf_ptr(out_abs_path)));
102 return ErrorNone;
103}
104
86void os_exec_process(const char *exe, ZigList<const char *> &args,105void os_exec_process(const char *exe, ZigList<const char *> &args,
87 int *return_code, Buf *out_stderr, Buf *out_stdout)106 int *return_code, Buf *out_stderr, Buf *out_stdout)
88{107{
src/os.hpp+1
...@@ -19,6 +19,7 @@ void os_exec_process(const char *exe, ZigList<const char *> &args,...@@ -19,6 +19,7 @@ void os_exec_process(const char *exe, ZigList<const char *> &args,
1919
20void os_path_split(Buf *full_path, Buf *out_dirname, Buf *out_basename);20void os_path_split(Buf *full_path, Buf *out_dirname, Buf *out_basename);
21void os_path_join(Buf *dirname, Buf *basename, Buf *out_full_path);21void os_path_join(Buf *dirname, Buf *basename, Buf *out_full_path);
22int os_path_real(Buf *rel_path, Buf *out_abs_path);
2223
23void os_write_file(Buf *full_path, Buf *contents);24void os_write_file(Buf *full_path, Buf *contents);
2425
src/parser.cpp+28-25
...@@ -1113,38 +1113,41 @@ static AstNode *ast_parse_suffix_op_expr(ParseContext *pc, int *token_index, boo...@@ -1113,38 +1113,41 @@ static AstNode *ast_parse_suffix_op_expr(ParseContext *pc, int *token_index, boo
1113 return nullptr;1113 return nullptr;
1114 }1114 }
11151115
1116 Token *token = &pc->tokens->at(*token_index);1116 while (true) {
1117 if (token->id == TokenIdLParen) {1117 Token *token = &pc->tokens->at(*token_index);
1118 *token_index += 1;1118 if (token->id == TokenIdLParen) {
1119 *token_index += 1;
11191120
1120 AstNode *node = ast_create_node(pc, NodeTypeFnCallExpr, token);1121 AstNode *node = ast_create_node(pc, NodeTypeFnCallExpr, token);
1121 node->data.fn_call_expr.fn_ref_expr = primary_expr;1122 node->data.fn_call_expr.fn_ref_expr = primary_expr;
1122 ast_parse_fn_call_param_list(pc, token_index, &node->data.fn_call_expr.params);1123 ast_parse_fn_call_param_list(pc, token_index, &node->data.fn_call_expr.params);
1123 return node;
1124 } else if (token->id == TokenIdLBracket) {
1125 *token_index += 1;
11261124
1127 AstNode *node = ast_create_node(pc, NodeTypeArrayAccessExpr, token);1125 primary_expr = node;
1128 node->data.array_access_expr.array_ref_expr = primary_expr;1126 } else if (token->id == TokenIdLBracket) {
1129 node->data.array_access_expr.subscript = ast_parse_expression(pc, token_index, true);1127 *token_index += 1;
11301128
1131 Token *r_bracket = &pc->tokens->at(*token_index);1129 AstNode *node = ast_create_node(pc, NodeTypeArrayAccessExpr, token);
1132 *token_index += 1;1130 node->data.array_access_expr.array_ref_expr = primary_expr;
1133 ast_expect_token(pc, r_bracket, TokenIdRBracket);1131 node->data.array_access_expr.subscript = ast_parse_expression(pc, token_index, true);
11341132
1135 return node;1133 Token *r_bracket = &pc->tokens->at(*token_index);
1136 } else if (token->id == TokenIdDot) {1134 *token_index += 1;
1137 *token_index += 1;1135 ast_expect_token(pc, r_bracket, TokenIdRBracket);
11381136
1139 Token *name_token = ast_eat_token(pc, token_index, TokenIdSymbol);1137 primary_expr = node;
1138 } else if (token->id == TokenIdDot) {
1139 *token_index += 1;
11401140
1141 AstNode *node = ast_create_node(pc, NodeTypeFieldAccessExpr, token);1141 Token *name_token = ast_eat_token(pc, token_index, TokenIdSymbol);
1142 node->data.field_access_expr.struct_expr = primary_expr;
1143 ast_buf_from_token(pc, name_token, &node->data.field_access_expr.field_name);
11441142
1145 return node;1143 AstNode *node = ast_create_node(pc, NodeTypeFieldAccessExpr, token);
1146 } else {1144 node->data.field_access_expr.struct_expr = primary_expr;
1147 return primary_expr;1145 ast_buf_from_token(pc, name_token, &node->data.field_access_expr.field_name);
1146
1147 primary_expr = node;
1148 } else {
1149 return primary_expr;
1150 }
1148 }1151 }
1149}1152}
11501153