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 @@
22export library "mathtest";
33
44export fn add(a: i32, b: i32) -> i32 {
5 return a + b;
5 a + b
66}
src/analyze.cpp+47-13
......@@ -74,7 +74,7 @@ TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool
7474 }
7575}
7676
77static void resolve_type(CodeGen *g, AstNode *node) {
77static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node) {
7878 assert(!node->codegen_node);
7979 node->codegen_node = allocate<CodeGenNode>(1);
8080 TypeNode *type_node = &node->codegen_node->data.type_node;
......@@ -90,7 +90,7 @@ static void resolve_type(CodeGen *g, AstNode *node) {
9090 buf_sprintf("invalid type name: '%s'", buf_ptr(name)));
9191 type_node->entry = g->builtin_types.entry_invalid;
9292 }
93 break;
93 return type_node->entry;
9494 }
9595 case AstNodeTypeTypePointer:
9696 {
......@@ -101,12 +101,12 @@ static void resolve_type(CodeGen *g, AstNode *node) {
101101 buf_create_from_str("pointer to unreachable not allowed"));
102102 }
103103 type_node->entry = get_pointer_to_type(g, child_type, node->data.type.is_const);
104 break;
104 return type_node->entry;
105105 }
106106 }
107107}
108108
109static void resolve_function_proto(CodeGen *g, AstNode *node) {
109static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_table_entry) {
110110 assert(node->type == NodeTypeFnProto);
111111
112112 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) {
120120 AstNode *child = node->data.fn_proto.params.at(i);
121121 assert(child->type == NodeTypeParamDecl);
122122
123 // parameter names are not important here.
124
125 resolve_type(g, child->data.param_decl.type);
123 Buf *param_name = &child->data.param_decl.name;
124 SymbolTableEntry *symbol_entry = allocate<SymbolTableEntry>(1);
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);
126128 }
127129
128130 resolve_type(g, node->data.fn_proto.return_type);
......@@ -148,20 +150,26 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import,
148150 assert(fn_decl->type == NodeTypeFnDecl);
149151 AstNode *fn_proto = fn_decl->data.fn_decl.fn_proto;
150152 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
154154 FnTableEntry *fn_table_entry = allocate<FnTableEntry>(1);
155155 fn_table_entry->proto_node = fn_proto;
156156 fn_table_entry->is_extern = true;
157157 fn_table_entry->calling_convention = LLVMCCallConv;
158158 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;
160164 g->fn_protos.append(fn_table_entry);
161165 import->fn_table.put(name, fn_table_entry);
162166 if (is_pub) {
163167 g->fn_table.put(name, fn_table_entry);
164168 }
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;
165173 }
166174 break;
167175 case NodeTypeFnDef:
......@@ -198,6 +206,7 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import,
198206 fn_table_entry->fn_def_node = node;
199207 fn_table_entry->internal_linkage = is_internal;
200208 fn_table_entry->calling_convention = is_internal ? LLVMFastCallConv : LLVMCCallConv;
209 fn_table_entry->symbol_table.init(8);
201210
202211 g->fn_protos.append(fn_table_entry);
203212 g->fn_defs.append(fn_table_entry);
......@@ -207,7 +216,11 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import,
207216 g->fn_table.put(proto_name, fn_table_entry);
208217 }
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;
211224 }
212225 }
213226 break;
......@@ -289,6 +302,16 @@ static TypeTableEntry * get_return_type(BlockContext *context) {
289302 return return_type_node->codegen_node->data.type_node.entry;
290303}
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
292315static void check_type_compatibility(CodeGen *g, AstNode *node, TypeTableEntry *expected_type, TypeTableEntry *actual_type) {
293316 if (expected_type == nullptr)
294317 return; // anything will do
......@@ -482,9 +505,20 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
482505 break;
483506
484507 case NodeTypeSymbol:
485 // look up symbol in symbol table
486 zig_panic("TODO analyze_expression symbol");
487
508 {
509 Buf *symbol_name = &node->data.symbol;
510 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 }
488522 case NodeTypeCastExpr:
489523 zig_panic("TODO analyze_expression cast expr");
490524 break;
src/codegen.cpp+7-13
......@@ -105,19 +105,13 @@ static LLVMValueRef find_or_create_string(CodeGen *g, Buf *str) {
105105
106106static LLVMValueRef get_variable_value(CodeGen *g, Buf *name) {
107107 assert(g->cur_fn->proto_node->type == NodeTypeFnProto);
108 int param_count = g->cur_fn->proto_node->data.fn_proto.params.length;
109 for (int i = 0; i < param_count; i += 1) {
110 AstNode *param_decl_node = g->cur_fn->proto_node->data.fn_proto.params.at(i);
111 assert(param_decl_node->type == NodeTypeParamDecl);
112 Buf *param_name = &param_decl_node->data.param_decl.name;
113 if (buf_eql_buf(name, param_name)) {
114 CodeGenNode *codegen_node = g->cur_fn->fn_def_node->codegen_node;
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();
108
109 SymbolTableEntry *symbol_entry = g->cur_fn->symbol_table.get(name);
110
111 CodeGenNode *codegen_node = g->cur_fn->fn_def_node->codegen_node;
112 assert(codegen_node);
113 FnDefNode *codegen_fn_def = &codegen_node->data.fn_def_node;
114 return codegen_fn_def->params[symbol_entry->param_index];
121115}
122116
123117static TypeTableEntry *get_expr_type(AstNode *node) {
src/semantic_info.hpp+13
......@@ -38,6 +38,11 @@ struct ImportTableEntry {
3838 HashMap<Buf *, FnTableEntry *, buf_hash, buf_eql_buf> fn_table;
3939};
4040
41struct SymbolTableEntry {
42 TypeTableEntry *type_entry;
43 int param_index; // only valid in the case of parameters
44};
45
4146struct FnTableEntry {
4247 LLVMValueRef fn_value;
4348 AstNode *proto_node;
......@@ -46,6 +51,9 @@ struct FnTableEntry {
4651 bool internal_linkage;
4752 unsigned calling_convention;
4853 ImportTableEntry *import_entry;
54
55 // reminder: hash tables must be initialized before use
56 HashMap<Buf *, SymbolTableEntry *, buf_hash, buf_eql_buf> symbol_table;
4957};
5058
5159struct CodeGen {
......@@ -106,6 +114,10 @@ struct TypeNode {
106114 TypeTableEntry *entry;
107115};
108116
117struct FnProtoNode {
118 FnTableEntry *fn_table_entry;
119};
120
109121struct FnDefNode {
110122 TypeTableEntry *implicit_return_type;
111123 bool skip;
......@@ -121,6 +133,7 @@ struct CodeGenNode {
121133 TypeNode type_node; // for NodeTypeType
122134 FnDefNode fn_def_node; // for NodeTypeFnDef
123135 ExprNode expr_node; // for all the expression nodes
136 FnProtoNode fn_proto_node; // for NodeTypeFnProto
124137 } data;
125138};
126139
test/run_tests.cpp+19
......@@ -213,6 +213,25 @@ static void add_compiling_test_cases(void) {
213213 exit(0);
214214 }
215215 )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");
216235}
217236
218237static void add_compile_failure_test_cases(void) {