authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2015-12-02 00:53:57-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2015-12-02 00:53:57-07:00
log370de7386ce811b6381c3ffcf5dd8efd2810da2b
tree3d3025ca84b7d5a34c8f835842f3cd78f123891e
parent08a2311efd8b388cd431feb6000741f4a62da613

fix parameter access and thus shared library example


5 files changed, 87 insertions(+), 27 deletions(-)

example/shared_library/mathtest.zig+1-1
...@@ -2,5 +2,5 @@...@@ -2,5 +2,5 @@
2export library "mathtest";2export library "mathtest";
33
4export fn add(a: i32, b: i32) -> i32 {4export fn add(a: i32, b: i32) -> i32 {
5 return a + b;5 a + b
6}6}
src/analyze.cpp+47-13
...@@ -74,7 +74,7 @@ TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool...@@ -74,7 +74,7 @@ TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool
74 }74 }
75}75}
7676
77static void resolve_type(CodeGen *g, AstNode *node) {77static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node) {
78 assert(!node->codegen_node);78 assert(!node->codegen_node);
79 node->codegen_node = allocate<CodeGenNode>(1);79 node->codegen_node = allocate<CodeGenNode>(1);
80 TypeNode *type_node = &node->codegen_node->data.type_node;80 TypeNode *type_node = &node->codegen_node->data.type_node;
...@@ -90,7 +90,7 @@ static void resolve_type(CodeGen *g, AstNode *node) {...@@ -90,7 +90,7 @@ static void resolve_type(CodeGen *g, AstNode *node) {
90 buf_sprintf("invalid type name: '%s'", buf_ptr(name)));90 buf_sprintf("invalid type name: '%s'", buf_ptr(name)));
91 type_node->entry = g->builtin_types.entry_invalid;91 type_node->entry = g->builtin_types.entry_invalid;
92 }92 }
93 break;93 return type_node->entry;
94 }94 }
95 case AstNodeTypeTypePointer:95 case AstNodeTypeTypePointer:
96 {96 {
...@@ -101,12 +101,12 @@ static void resolve_type(CodeGen *g, AstNode *node) {...@@ -101,12 +101,12 @@ static void resolve_type(CodeGen *g, AstNode *node) {
101 buf_create_from_str("pointer to unreachable not allowed"));101 buf_create_from_str("pointer to unreachable not allowed"));
102 }102 }
103 type_node->entry = get_pointer_to_type(g, child_type, node->data.type.is_const);103 type_node->entry = get_pointer_to_type(g, child_type, node->data.type.is_const);
104 break;104 return type_node->entry;
105 }105 }
106 }106 }
107}107}
108108
109static void resolve_function_proto(CodeGen *g, AstNode *node) {109static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_table_entry) {
110 assert(node->type == NodeTypeFnProto);110 assert(node->type == NodeTypeFnProto);
111111
112 for (int i = 0; i < node->data.fn_proto.directives->length; i += 1) {112 for (int i = 0; i < node->data.fn_proto.directives->length; i += 1) {
...@@ -120,9 +120,11 @@ static void resolve_function_proto(CodeGen *g, AstNode *node) {...@@ -120,9 +120,11 @@ static void resolve_function_proto(CodeGen *g, AstNode *node) {
120 AstNode *child = node->data.fn_proto.params.at(i);120 AstNode *child = node->data.fn_proto.params.at(i);
121 assert(child->type == NodeTypeParamDecl);121 assert(child->type == NodeTypeParamDecl);
122122
123 // parameter names are not important here.123 Buf *param_name = &child->data.param_decl.name;
124124 SymbolTableEntry *symbol_entry = allocate<SymbolTableEntry>(1);
125 resolve_type(g, child->data.param_decl.type);125 symbol_entry->type_entry = resolve_type(g, child->data.param_decl.type);
126 symbol_entry->param_index = i;
127 fn_table_entry->symbol_table.put(param_name, symbol_entry);
126 }128 }
127129
128 resolve_type(g, node->data.fn_proto.return_type);130 resolve_type(g, node->data.fn_proto.return_type);
...@@ -148,20 +150,26 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import,...@@ -148,20 +150,26 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import,
148 assert(fn_decl->type == NodeTypeFnDecl);150 assert(fn_decl->type == NodeTypeFnDecl);
149 AstNode *fn_proto = fn_decl->data.fn_decl.fn_proto;151 AstNode *fn_proto = fn_decl->data.fn_decl.fn_proto;
150 bool is_pub = (fn_proto->data.fn_proto.visib_mod == FnProtoVisibModPub);152 bool is_pub = (fn_proto->data.fn_proto.visib_mod == FnProtoVisibModPub);
151 resolve_function_proto(g, fn_proto);
152 Buf *name = &fn_proto->data.fn_proto.name;
153153
154 FnTableEntry *fn_table_entry = allocate<FnTableEntry>(1);154 FnTableEntry *fn_table_entry = allocate<FnTableEntry>(1);
155 fn_table_entry->proto_node = fn_proto;155 fn_table_entry->proto_node = fn_proto;
156 fn_table_entry->is_extern = true;156 fn_table_entry->is_extern = true;
157 fn_table_entry->calling_convention = LLVMCCallConv;157 fn_table_entry->calling_convention = LLVMCCallConv;
158 fn_table_entry->import_entry = import;158 fn_table_entry->import_entry = import;
159 fn_table_entry->symbol_table.init(8);
160
161 resolve_function_proto(g, fn_proto, fn_table_entry);
159162
163 Buf *name = &fn_proto->data.fn_proto.name;
160 g->fn_protos.append(fn_table_entry);164 g->fn_protos.append(fn_table_entry);
161 import->fn_table.put(name, fn_table_entry);165 import->fn_table.put(name, fn_table_entry);
162 if (is_pub) {166 if (is_pub) {
163 g->fn_table.put(name, fn_table_entry);167 g->fn_table.put(name, fn_table_entry);
164 }168 }
169
170 assert(!fn_proto->codegen_node);
171 fn_proto->codegen_node = allocate<CodeGenNode>(1);
172 fn_proto->codegen_node->data.fn_proto_node.fn_table_entry = fn_table_entry;
165 }173 }
166 break;174 break;
167 case NodeTypeFnDef:175 case NodeTypeFnDef:
...@@ -198,6 +206,7 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import,...@@ -198,6 +206,7 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import,
198 fn_table_entry->fn_def_node = node;206 fn_table_entry->fn_def_node = node;
199 fn_table_entry->internal_linkage = is_internal;207 fn_table_entry->internal_linkage = is_internal;
200 fn_table_entry->calling_convention = is_internal ? LLVMFastCallConv : LLVMCCallConv;208 fn_table_entry->calling_convention = is_internal ? LLVMFastCallConv : LLVMCCallConv;
209 fn_table_entry->symbol_table.init(8);
201210
202 g->fn_protos.append(fn_table_entry);211 g->fn_protos.append(fn_table_entry);
203 g->fn_defs.append(fn_table_entry);212 g->fn_defs.append(fn_table_entry);
...@@ -207,7 +216,11 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import,...@@ -207,7 +216,11 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import,
207 g->fn_table.put(proto_name, fn_table_entry);216 g->fn_table.put(proto_name, fn_table_entry);
208 }217 }
209218
210 resolve_function_proto(g, proto_node);219 resolve_function_proto(g, proto_node, fn_table_entry);
220
221 assert(!proto_node->codegen_node);
222 proto_node->codegen_node = allocate<CodeGenNode>(1);
223 proto_node->codegen_node->data.fn_proto_node.fn_table_entry = fn_table_entry;
211 }224 }
212 }225 }
213 break;226 break;
...@@ -289,6 +302,16 @@ static TypeTableEntry * get_return_type(BlockContext *context) {...@@ -289,6 +302,16 @@ static TypeTableEntry * get_return_type(BlockContext *context) {
289 return return_type_node->codegen_node->data.type_node.entry;302 return return_type_node->codegen_node->data.type_node.entry;
290}303}
291304
305static FnTableEntry *get_context_fn_entry(BlockContext *context) {
306 AstNode *fn_def_node = context->root->node;
307 assert(fn_def_node->type == NodeTypeFnDef);
308 AstNode *fn_proto_node = fn_def_node->data.fn_def.fn_proto;
309 assert(fn_proto_node->type == NodeTypeFnProto);
310 assert(fn_proto_node->codegen_node);
311 assert(fn_proto_node->codegen_node->data.fn_proto_node.fn_table_entry);
312 return fn_proto_node->codegen_node->data.fn_proto_node.fn_table_entry;
313}
314
292static void check_type_compatibility(CodeGen *g, AstNode *node, TypeTableEntry *expected_type, TypeTableEntry *actual_type) {315static void check_type_compatibility(CodeGen *g, AstNode *node, TypeTableEntry *expected_type, TypeTableEntry *actual_type) {
293 if (expected_type == nullptr)316 if (expected_type == nullptr)
294 return; // anything will do317 return; // anything will do
...@@ -482,9 +505,20 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,...@@ -482,9 +505,20 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
482 break;505 break;
483506
484 case NodeTypeSymbol:507 case NodeTypeSymbol:
485 // look up symbol in symbol table508 {
486 zig_panic("TODO analyze_expression symbol");509 Buf *symbol_name = &node->data.symbol;
487510 FnTableEntry *fn_table_entry = get_context_fn_entry(context);
511 auto table_entry = fn_table_entry->symbol_table.maybe_get(symbol_name);
512 if (table_entry) {
513 SymbolTableEntry *symbol_entry = table_entry->value;
514 return_type = symbol_entry->type_entry;
515 } else {
516 add_node_error(g, node,
517 buf_sprintf("use of undeclared identifier '%s'", buf_ptr(symbol_name)));
518 return_type = g->builtin_types.entry_invalid;
519 }
520 break;
521 }
488 case NodeTypeCastExpr:522 case NodeTypeCastExpr:
489 zig_panic("TODO analyze_expression cast expr");523 zig_panic("TODO analyze_expression cast expr");
490 break;524 break;
src/codegen.cpp+7-13
...@@ -105,19 +105,13 @@ static LLVMValueRef find_or_create_string(CodeGen *g, Buf *str) {...@@ -105,19 +105,13 @@ static LLVMValueRef find_or_create_string(CodeGen *g, Buf *str) {
105105
106static LLVMValueRef get_variable_value(CodeGen *g, Buf *name) {106static LLVMValueRef get_variable_value(CodeGen *g, Buf *name) {
107 assert(g->cur_fn->proto_node->type == NodeTypeFnProto);107 assert(g->cur_fn->proto_node->type == NodeTypeFnProto);
108 int param_count = g->cur_fn->proto_node->data.fn_proto.params.length;108
109 for (int i = 0; i < param_count; i += 1) {109 SymbolTableEntry *symbol_entry = g->cur_fn->symbol_table.get(name);
110 AstNode *param_decl_node = g->cur_fn->proto_node->data.fn_proto.params.at(i);110
111 assert(param_decl_node->type == NodeTypeParamDecl);111 CodeGenNode *codegen_node = g->cur_fn->fn_def_node->codegen_node;
112 Buf *param_name = &param_decl_node->data.param_decl.name;112 assert(codegen_node);
113 if (buf_eql_buf(name, param_name)) {113 FnDefNode *codegen_fn_def = &codegen_node->data.fn_def_node;
114 CodeGenNode *codegen_node = g->cur_fn->fn_def_node->codegen_node;114 return codegen_fn_def->params[symbol_entry->param_index];
115 assert(codegen_node);
116 FnDefNode *codegen_fn_def = &codegen_node->data.fn_def_node;
117 return codegen_fn_def->params[i];
118 }
119 }
120 zig_unreachable();
121}115}
122116
123static TypeTableEntry *get_expr_type(AstNode *node) {117static TypeTableEntry *get_expr_type(AstNode *node) {
src/semantic_info.hpp+13
...@@ -38,6 +38,11 @@ struct ImportTableEntry {...@@ -38,6 +38,11 @@ struct ImportTableEntry {
38 HashMap<Buf *, FnTableEntry *, buf_hash, buf_eql_buf> fn_table;38 HashMap<Buf *, FnTableEntry *, buf_hash, buf_eql_buf> fn_table;
39};39};
4040
41struct SymbolTableEntry {
42 TypeTableEntry *type_entry;
43 int param_index; // only valid in the case of parameters
44};
45
41struct FnTableEntry {46struct FnTableEntry {
42 LLVMValueRef fn_value;47 LLVMValueRef fn_value;
43 AstNode *proto_node;48 AstNode *proto_node;
...@@ -46,6 +51,9 @@ struct FnTableEntry {...@@ -46,6 +51,9 @@ struct FnTableEntry {
46 bool internal_linkage;51 bool internal_linkage;
47 unsigned calling_convention;52 unsigned calling_convention;
48 ImportTableEntry *import_entry;53 ImportTableEntry *import_entry;
54
55 // reminder: hash tables must be initialized before use
56 HashMap<Buf *, SymbolTableEntry *, buf_hash, buf_eql_buf> symbol_table;
49};57};
5058
51struct CodeGen {59struct CodeGen {
...@@ -106,6 +114,10 @@ struct TypeNode {...@@ -106,6 +114,10 @@ struct TypeNode {
106 TypeTableEntry *entry;114 TypeTableEntry *entry;
107};115};
108116
117struct FnProtoNode {
118 FnTableEntry *fn_table_entry;
119};
120
109struct FnDefNode {121struct FnDefNode {
110 TypeTableEntry *implicit_return_type;122 TypeTableEntry *implicit_return_type;
111 bool skip;123 bool skip;
...@@ -121,6 +133,7 @@ struct CodeGenNode {...@@ -121,6 +133,7 @@ struct CodeGenNode {
121 TypeNode type_node; // for NodeTypeType133 TypeNode type_node; // for NodeTypeType
122 FnDefNode fn_def_node; // for NodeTypeFnDef134 FnDefNode fn_def_node; // for NodeTypeFnDef
123 ExprNode expr_node; // for all the expression nodes135 ExprNode expr_node; // for all the expression nodes
136 FnProtoNode fn_proto_node; // for NodeTypeFnProto
124 } data;137 } data;
125};138};
126139
test/run_tests.cpp+19
...@@ -213,6 +213,25 @@ static void add_compiling_test_cases(void) {...@@ -213,6 +213,25 @@ static void add_compiling_test_cases(void) {
213 exit(0);213 exit(0);
214 }214 }
215 )SOURCE", "1 is true\n!0 is true\n");215 )SOURCE", "1 is true\n!0 is true\n");
216
217 add_simple_case("params", R"SOURCE(
218 #link("c")
219 extern {
220 fn puts(s: *const u8) -> i32;
221 fn exit(code: i32) -> unreachable;
222 }
223
224 fn add(a: i32, b: i32) -> i32 {
225 a + b
226 }
227
228 export fn _start() -> unreachable {
229 if add(22, 11) == 33 {
230 puts("pass");
231 }
232 exit(0);
233 }
234 )SOURCE", "pass\n");
216}235}
217236
218static void add_compile_failure_test_cases(void) {237static void add_compile_failure_test_cases(void) {