authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-18 08:50:10-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-18 08:50:10-07:00
log3a326d50051ad8b65639e5e2bbe45e41a8b35591
tree797dc5661ae401c4d75971fb8c722a8834cfb2c9
parent4c50606b9d41c2c3d9f25dc8bf0848e30e338f6e

pave the road for function pointers

See #14

7 files changed, 110 insertions(+), 137 deletions(-)

src/all_types.hpp+2-6
...@@ -793,11 +793,6 @@ struct LabelTableEntry {...@@ -793,11 +793,6 @@ struct LabelTableEntry {
793 bool entered_from_fallthrough;793 bool entered_from_fallthrough;
794};794};
795795
796enum FnAttrId {
797 FnAttrIdNaked,
798 FnAttrIdAlwaysInline,
799};
800
801struct FnTableEntry {796struct FnTableEntry {
802 LLVMValueRef fn_value;797 LLVMValueRef fn_value;
803 AstNode *proto_node;798 AstNode *proto_node;
...@@ -806,7 +801,8 @@ struct FnTableEntry {...@@ -806,7 +801,8 @@ struct FnTableEntry {
806 bool internal_linkage;801 bool internal_linkage;
807 unsigned calling_convention;802 unsigned calling_convention;
808 ImportTableEntry *import_entry;803 ImportTableEntry *import_entry;
809 ZigList<FnAttrId> fn_attr_list;804 bool is_naked;
805 bool is_inline;
810 // Required to be a pre-order traversal of the AST. (parents must come before children)806 // Required to be a pre-order traversal of the AST. (parents must come before children)
811 ZigList<BlockContext *> all_block_contexts;807 ZigList<BlockContext *> all_block_contexts;
812 TypeTableEntry *member_of_struct;808 TypeTableEntry *member_of_struct;
src/analyze.cpp+90-30
...@@ -346,18 +346,19 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t...@@ -346,18 +346,19 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t
346 ImportTableEntry *import)346 ImportTableEntry *import)
347{347{
348 assert(node->type == NodeTypeFnProto);348 assert(node->type == NodeTypeFnProto);
349 AstNodeFnProto *fn_proto = &node->data.fn_proto;
349350
350 for (int i = 0; i < node->data.fn_proto.directives->length; i += 1) {351 for (int i = 0; i < fn_proto->directives->length; i += 1) {
351 AstNode *directive_node = node->data.fn_proto.directives->at(i);352 AstNode *directive_node = fn_proto->directives->at(i);
352 Buf *name = &directive_node->data.directive.name;353 Buf *name = &directive_node->data.directive.name;
353354
354 if (buf_eql_str(name, "attribute")) {355 if (buf_eql_str(name, "attribute")) {
355 Buf *attr_name = &directive_node->data.directive.param;356 Buf *attr_name = &directive_node->data.directive.param;
356 if (fn_table_entry->fn_def_node) {357 if (fn_table_entry->fn_def_node) {
357 if (buf_eql_str(attr_name, "naked")) {358 if (buf_eql_str(attr_name, "naked")) {
358 fn_table_entry->fn_attr_list.append(FnAttrIdNaked);359 fn_table_entry->is_naked = true;
359 } else if (buf_eql_str(attr_name, "inline")) {360 } else if (buf_eql_str(attr_name, "inline")) {
360 fn_table_entry->fn_attr_list.append(FnAttrIdAlwaysInline);361 fn_table_entry->is_inline = true;
361 } else {362 } else {
362 add_node_error(g, directive_node,363 add_node_error(g, directive_node,
363 buf_sprintf("invalid function attribute: '%s'", buf_ptr(name)));364 buf_sprintf("invalid function attribute: '%s'", buf_ptr(name)));
...@@ -382,38 +383,100 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t...@@ -382,38 +383,100 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t
382383
383 buf_resize(&fn_type->name, 0);384 buf_resize(&fn_type->name, 0);
384 buf_appendf(&fn_type->name, "fn(");385 buf_appendf(&fn_type->name, "fn(");
386 int gen_param_count = 0;
387 LLVMTypeRef *gen_param_types = allocate<LLVMTypeRef>(param_count);
388 LLVMZigDIType **param_di_types = allocate<LLVMZigDIType*>(1 + param_count);
385 for (int i = 0; i < param_count; i += 1) {389 for (int i = 0; i < param_count; i += 1) {
386 AstNode *child = node->data.fn_proto.params.at(i);390 AstNode *child = node->data.fn_proto.params.at(i);
387 assert(child->type == NodeTypeParamDecl);391 assert(child->type == NodeTypeParamDecl);
388 TypeTableEntry *type_entry = analyze_type_expr(g, import, import->block_context,392 TypeTableEntry *type_entry = analyze_type_expr(g, import, import->block_context,
389 child->data.param_decl.type);393 child->data.param_decl.type);
390 fn_table_entry->type_entry->data.fn.param_types[i] = type_entry;394 fn_type->data.fn.param_types[i] = type_entry;
391
392 buf_appendf(&fn_type->name, "%s", buf_ptr(&type_entry->name));
393
394 if (i + 1 < param_count) {
395 buf_appendf(&fn_type->name, ", ");
396 }
397395
398 if (type_entry->id == TypeTableEntryIdUnreachable) {396 if (type_entry->id == TypeTableEntryIdUnreachable) {
399 add_node_error(g, child->data.param_decl.type,397 add_node_error(g, child->data.param_decl.type,
400 buf_sprintf("parameter of type 'unreachable' not allowed"));398 buf_sprintf("parameter of type 'unreachable' not allowed"));
401 } else if (type_entry->id == TypeTableEntryIdVoid) {399 fn_proto->skip = true;
402 if (node->data.fn_proto.visib_mod == VisibModExport) {400 } else if (type_entry->id == TypeTableEntryIdInvalid) {
403 add_node_error(g, child->data.param_decl.type,401 fn_proto->skip = true;
404 buf_sprintf("parameter of type 'void' not allowed on exported functions"));402 }
405 }403
404 if (!fn_proto->skip && type_entry->size_in_bits > 0) {
405 const char *comma = (gen_param_count == 0) ? "" : ", ";
406 buf_appendf(&fn_type->name, "%s%s", comma, buf_ptr(&type_entry->name));
407
408 TypeTableEntry *gen_type = handle_is_ptr(type_entry) ?
409 get_pointer_to_type(g, type_entry, true) : type_entry;
410 gen_param_types[gen_param_count] = gen_type->type_ref;
411
412 gen_param_count += 1;
413
414 // after the gen_param_count += 1 because 0 is the return type
415 param_di_types[gen_param_count] = gen_type->di_type;
406 }416 }
407 }417 }
408418
409 TypeTableEntry *return_type = analyze_type_expr(g, import, import->block_context,419 TypeTableEntry *return_type = analyze_type_expr(g, import, import->block_context,
410 node->data.fn_proto.return_type);420 node->data.fn_proto.return_type);
411 fn_table_entry->type_entry->data.fn.return_type = return_type;421 fn_type->data.fn.return_type = return_type;
422 if (return_type->id == TypeTableEntryIdInvalid) {
423 fn_proto->skip = true;
424 }
412425
413 buf_appendf(&fn_type->name, ")");426 buf_appendf(&fn_type->name, ")");
414 if (return_type->id != TypeTableEntryIdVoid) {427 if (return_type->id != TypeTableEntryIdVoid) {
415 buf_appendf(&fn_type->name, " %s", buf_ptr(&return_type->name));428 buf_appendf(&fn_type->name, " %s", buf_ptr(&return_type->name));
416 }429 }
430
431 if (fn_proto->skip) {
432 return;
433 }
434
435 fn_type->type_ref = LLVMFunctionType(return_type->type_ref, gen_param_types, gen_param_count,
436 fn_proto->is_var_args);
437
438 fn_table_entry->fn_value = LLVMAddFunction(g->module, buf_ptr(&fn_table_entry->symbol_name),
439 fn_table_entry->type_entry->type_ref);
440
441 if (fn_table_entry->is_inline) {
442 LLVMAddFunctionAttr(fn_table_entry->fn_value, LLVMAlwaysInlineAttribute);
443 }
444 if (fn_table_entry->is_naked) {
445 LLVMAddFunctionAttr(fn_table_entry->fn_value, LLVMNakedAttribute);
446 }
447
448 LLVMSetLinkage(fn_table_entry->fn_value, fn_table_entry->internal_linkage ?
449 LLVMInternalLinkage : LLVMExternalLinkage);
450
451 if (return_type->id == TypeTableEntryIdUnreachable) {
452 LLVMAddFunctionAttr(fn_table_entry->fn_value, LLVMNoReturnAttribute);
453 }
454 LLVMSetFunctionCallConv(fn_table_entry->fn_value, fn_table_entry->calling_convention);
455 if (!fn_table_entry->is_extern) {
456 LLVMAddFunctionAttr(fn_table_entry->fn_value, LLVMNoUnwindAttribute);
457 }
458
459 param_di_types[0] = return_type->di_type;
460 LLVMZigDISubroutineType *di_sub_type = LLVMZigCreateSubroutineType(g->dbuilder, import->di_file,
461 param_di_types, gen_param_count + 1, 0);
462
463 // Add debug info.
464 unsigned line_number = node->line + 1;
465 unsigned scope_line = line_number;
466 bool is_definition = fn_table_entry->fn_def_node != nullptr;
467 unsigned flags = 0;
468 bool is_optimized = g->build_type == CodeGenBuildTypeRelease;
469 LLVMZigDISubprogram *subprogram = LLVMZigCreateFunction(g->dbuilder,
470 import->block_context->di_scope, buf_ptr(&fn_table_entry->symbol_name), "",
471 import->di_file, line_number,
472 di_sub_type, fn_table_entry->internal_linkage,
473 is_definition, scope_line, flags, is_optimized, fn_table_entry->fn_value);
474 fn_type->di_type = LLVMZigSubroutineToType(di_sub_type);
475 if (fn_table_entry->fn_def_node) {
476 BlockContext *context = new_block_context(fn_table_entry->fn_def_node, import->block_context);
477 fn_table_entry->fn_def_node->data.fn_def.block_context = context;
478 context->di_scope = LLVMZigSubprogramToScope(subprogram);
479 }
417}480}
418481
419static void preview_function_labels(CodeGen *g, AstNode *node, FnTableEntry *fn_table_entry) {482static void preview_function_labels(CodeGen *g, AstNode *node, FnTableEntry *fn_table_entry) {
...@@ -724,14 +787,6 @@ static void preview_fn_proto(CodeGen *g, ImportTableEntry *import,...@@ -724,14 +787,6 @@ static void preview_fn_proto(CodeGen *g, ImportTableEntry *import,
724 buf_sprintf("redefinition of '%s'", buf_ptr(proto_name)));787 buf_sprintf("redefinition of '%s'", buf_ptr(proto_name)));
725 proto_node->data.fn_proto.skip = true;788 proto_node->data.fn_proto.skip = true;
726 skip = true;789 skip = true;
727 } else if (is_pub) {
728 // TODO is this else if branch a mistake?
729 auto entry = fn_table->maybe_get(proto_name);
730 if (entry) {
731 add_node_error(g, proto_node, buf_sprintf("redefinition of '%s'", buf_ptr(proto_name)));
732 proto_node->data.fn_proto.skip = true;
733 skip = true;
734 }
735 }790 }
736 if (!extern_node && proto_node->data.fn_proto.is_var_args) {791 if (!extern_node && proto_node->data.fn_proto.is_var_args) {
737 add_node_error(g, proto_node,792 add_node_error(g, proto_node,
...@@ -775,10 +830,8 @@ static void preview_fn_proto(CodeGen *g, ImportTableEntry *import,...@@ -775,10 +830,8 @@ static void preview_fn_proto(CodeGen *g, ImportTableEntry *import,
775 g->bootstrap_import->fn_table.put(proto_name, fn_table_entry);830 g->bootstrap_import->fn_table.put(proto_name, fn_table_entry);
776 }831 }
777832
778 resolve_function_proto(g, proto_node, fn_table_entry, import);
779
780
781 proto_node->data.fn_proto.fn_table_entry = fn_table_entry;833 proto_node->data.fn_proto.fn_table_entry = fn_table_entry;
834 resolve_function_proto(g, proto_node, fn_table_entry, import);
782835
783 if (fn_def_node) {836 if (fn_def_node) {
784 preview_function_labels(g, fn_def_node->data.fn_def.body, fn_table_entry);837 preview_function_labels(g, fn_def_node->data.fn_def.body, fn_table_entry);
...@@ -3146,8 +3199,7 @@ static void analyze_top_level_fn_def(CodeGen *g, ImportTableEntry *import, AstNo...@@ -3146,8 +3199,7 @@ static void analyze_top_level_fn_def(CodeGen *g, ImportTableEntry *import, AstNo
3146 return;3199 return;
3147 }3200 }
31483201
3149 BlockContext *context = new_block_context(node, import->block_context);3202 BlockContext *context = node->data.fn_def.block_context;
3150 node->data.fn_def.block_context = context;
31513203
3152 AstNodeFnProto *fn_proto = &fn_proto_node->data.fn_proto;3204 AstNodeFnProto *fn_proto = &fn_proto_node->data.fn_proto;
3153 bool is_exported = (fn_proto->visib_mod == VisibModExport);3205 bool is_exported = (fn_proto->visib_mod == VisibModExport);
...@@ -3923,3 +3975,11 @@ TypeTableEntry **get_int_type_ptr(CodeGen *g, bool is_signed, int size_in_bits)...@@ -3923,3 +3975,11 @@ TypeTableEntry **get_int_type_ptr(CodeGen *g, bool is_signed, int size_in_bits)
3923TypeTableEntry *get_int_type(CodeGen *g, bool is_signed, int size_in_bits) {3975TypeTableEntry *get_int_type(CodeGen *g, bool is_signed, int size_in_bits) {
3924 return *get_int_type_ptr(g, is_signed, size_in_bits);3976 return *get_int_type_ptr(g, is_signed, size_in_bits);
3925}3977}
3978
3979bool handle_is_ptr(TypeTableEntry *type_entry) {
3980 return type_entry->id == TypeTableEntryIdStruct ||
3981 (type_entry->id == TypeTableEntryIdEnum && type_entry->data.enumeration.gen_field_count != 0) ||
3982 type_entry->id == TypeTableEntryIdMaybe ||
3983 type_entry->id == TypeTableEntryIdArray;
3984}
3985
src/analyze.hpp+1-1
...@@ -23,5 +23,5 @@ TopLevelDecl *get_resolved_top_level_decl(AstNode *node);...@@ -23,5 +23,5 @@ TopLevelDecl *get_resolved_top_level_decl(AstNode *node);
23bool is_node_void_expr(AstNode *node);23bool is_node_void_expr(AstNode *node);
24TypeTableEntry **get_int_type_ptr(CodeGen *g, bool is_signed, int size_in_bits);24TypeTableEntry **get_int_type_ptr(CodeGen *g, bool is_signed, int size_in_bits);
25TypeTableEntry *get_int_type(CodeGen *g, bool is_signed, int size_in_bits);25TypeTableEntry *get_int_type(CodeGen *g, bool is_signed, int size_in_bits);
2626bool handle_is_ptr(TypeTableEntry *type_entry);
27#endif27#endif
src/codegen.cpp+11-96
...@@ -82,29 +82,13 @@ static TypeTableEntry *get_type_for_type_node(AstNode *node) {...@@ -82,29 +82,13 @@ static TypeTableEntry *get_type_for_type_node(AstNode *node) {
82 return const_val->data.x_type;82 return const_val->data.x_type;
83}83}
8484
85static TypeTableEntry *fn_proto_type_from_type_node(CodeGen *g, AstNode *type_node) {
86 TypeTableEntry *type_entry = get_type_for_type_node(type_node);
87
88 if (type_entry->id == TypeTableEntryIdStruct || type_entry->id == TypeTableEntryIdArray) {
89 return get_pointer_to_type(g, type_entry, true);
90 } else {
91 return type_entry;
92 }
93}
94
95static LLVMZigDIType *to_llvm_debug_type(CodeGen *g, AstNode *type_node) {
96 TypeTableEntry *type_entry = get_type_for_type_node(type_node);
97 return type_entry->di_type;
98}
99
100
101static bool type_is_unreachable(CodeGen *g, AstNode *type_node) {85static bool type_is_unreachable(CodeGen *g, AstNode *type_node) {
102 return get_type_for_type_node(type_node)->id == TypeTableEntryIdUnreachable;86 return get_type_for_type_node(type_node)->id == TypeTableEntryIdUnreachable;
103}87}
10488
105static bool is_param_decl_type_void(CodeGen *g, AstNode *param_decl_node) {89static bool is_param_decl_type_void(CodeGen *g, AstNode *param_decl_node) {
106 assert(param_decl_node->type == NodeTypeParamDecl);90 assert(param_decl_node->type == NodeTypeParamDecl);
107 return get_type_for_type_node(param_decl_node->data.param_decl.type)->id == TypeTableEntryIdVoid;91 return get_type_for_type_node(param_decl_node->data.param_decl.type)->size_in_bits == 0;
108}92}
10993
110static int count_non_void_params(CodeGen *g, ZigList<AstNode *> *params) {94static int count_non_void_params(CodeGen *g, ZigList<AstNode *> *params) {
...@@ -150,11 +134,14 @@ static TypeTableEntry *get_expr_type(AstNode *node) {...@@ -150,11 +134,14 @@ static TypeTableEntry *get_expr_type(AstNode *node) {
150 return expr->type_entry;134 return expr->type_entry;
151}135}
152136
153static bool handle_is_ptr(TypeTableEntry *type_entry) {137static TypeTableEntry *fn_proto_type_from_type_node(CodeGen *g, AstNode *type_node) {
154 return type_entry->id == TypeTableEntryIdStruct ||138 TypeTableEntry *type_entry = get_type_for_type_node(type_node);
155 (type_entry->id == TypeTableEntryIdEnum && type_entry->data.enumeration.gen_field_count != 0) ||139
156 type_entry->id == TypeTableEntryIdMaybe ||140 if (handle_is_ptr(type_entry)) {
157 type_entry->id == TypeTableEntryIdArray;141 return get_pointer_to_type(g, type_entry, true);
142 } else {
143 return type_entry;
144 }
158}145}
159146
160static LLVMValueRef gen_number_literal_raw(CodeGen *g, AstNode *source_node,147static LLVMValueRef gen_number_literal_raw(CodeGen *g, AstNode *source_node,
...@@ -2121,31 +2108,6 @@ static void build_label_blocks(CodeGen *g, AstNode *block_node) {...@@ -2121,31 +2108,6 @@ static void build_label_blocks(CodeGen *g, AstNode *block_node) {
21212108
2122}2109}
21232110
2124static LLVMZigDISubroutineType *create_di_function_type(CodeGen *g, AstNodeFnProto *fn_proto,
2125 LLVMZigDIFile *di_file)
2126{
2127 LLVMZigDIType **types = allocate<LLVMZigDIType*>(1 + fn_proto->params.length);
2128 types[0] = to_llvm_debug_type(g, fn_proto->return_type);
2129 int types_len = fn_proto->params.length + 1;
2130 for (int i = 0; i < fn_proto->params.length; i += 1) {
2131 AstNode *param_node = fn_proto->params.at(i);
2132 assert(param_node->type == NodeTypeParamDecl);
2133 LLVMZigDIType *param_type = to_llvm_debug_type(g, param_node->data.param_decl.type);
2134 types[i + 1] = param_type;
2135 }
2136 return LLVMZigCreateSubroutineType(g->dbuilder, di_file, types, types_len, 0);
2137}
2138
2139static LLVMAttribute to_llvm_fn_attr(FnAttrId attr_id) {
2140 switch (attr_id) {
2141 case FnAttrIdNaked:
2142 return LLVMNakedAttribute;
2143 case FnAttrIdAlwaysInline:
2144 return LLVMAlwaysInlineAttribute;
2145 }
2146 zig_unreachable();
2147}
2148
2149static void do_code_gen(CodeGen *g) {2111static void do_code_gen(CodeGen *g) {
2150 assert(!g->errors.length);2112 assert(!g->errors.length);
21512113
...@@ -2172,45 +2134,12 @@ static void do_code_gen(CodeGen *g) {...@@ -2172,45 +2134,12 @@ static void do_code_gen(CodeGen *g) {
2172 // Generate function prototypes2134 // Generate function prototypes
2173 for (int fn_proto_i = 0; fn_proto_i < g->fn_protos.length; fn_proto_i += 1) {2135 for (int fn_proto_i = 0; fn_proto_i < g->fn_protos.length; fn_proto_i += 1) {
2174 FnTableEntry *fn_table_entry = g->fn_protos.at(fn_proto_i);2136 FnTableEntry *fn_table_entry = g->fn_protos.at(fn_proto_i);
2175
2176 AstNode *proto_node = fn_table_entry->proto_node;2137 AstNode *proto_node = fn_table_entry->proto_node;
2177 assert(proto_node->type == NodeTypeFnProto);2138 assert(proto_node->type == NodeTypeFnProto);
2178 AstNodeFnProto *fn_proto = &proto_node->data.fn_proto;2139 AstNodeFnProto *fn_proto = &proto_node->data.fn_proto;
21792140
2180 LLVMTypeRef ret_type = get_type_for_type_node(fn_proto->return_type)->type_ref;
2181 int param_count = count_non_void_params(g, &fn_proto->params);
2182 LLVMTypeRef *param_types = allocate<LLVMTypeRef>(param_count);
2183 int gen_param_index = 0;
2184 for (int param_decl_i = 0; param_decl_i < fn_proto->params.length; param_decl_i += 1) {
2185 AstNode *param_node = fn_proto->params.at(param_decl_i);
2186 assert(param_node->type == NodeTypeParamDecl);
2187 if (is_param_decl_type_void(g, param_node))
2188 continue;
2189 AstNode *type_node = param_node->data.param_decl.type;
2190 param_types[gen_param_index] = fn_proto_type_from_type_node(g, type_node)->type_ref;
2191 gen_param_index += 1;
2192 }
2193 LLVMTypeRef function_type = LLVMFunctionType(ret_type, param_types, param_count, fn_proto->is_var_args);
2194
2195 LLVMValueRef fn = LLVMAddFunction(g->module, buf_ptr(&fn_table_entry->symbol_name), function_type);
2196
2197 for (int attr_i = 0; attr_i < fn_table_entry->fn_attr_list.length; attr_i += 1) {
2198 FnAttrId attr_id = fn_table_entry->fn_attr_list.at(attr_i);
2199 LLVMAddFunctionAttr(fn, to_llvm_fn_attr(attr_id));
2200 }
2201
2202 LLVMSetLinkage(fn, fn_table_entry->internal_linkage ? LLVMInternalLinkage : LLVMExternalLinkage);
2203
2204 if (type_is_unreachable(g, fn_proto->return_type)) {
2205 LLVMAddFunctionAttr(fn, LLVMNoReturnAttribute);
2206 }
2207 LLVMSetFunctionCallConv(fn, fn_table_entry->calling_convention);
2208 if (!fn_table_entry->is_extern) {
2209 LLVMAddFunctionAttr(fn, LLVMNoUnwindAttribute);
2210 }
2211
2212 // set parameter attributes2141 // set parameter attributes
2213 gen_param_index = 0;2142 int gen_param_index = 0;
2214 for (int param_decl_i = 0; param_decl_i < fn_proto->params.length; param_decl_i += 1) {2143 for (int param_decl_i = 0; param_decl_i < fn_proto->params.length; param_decl_i += 1) {
2215 AstNode *param_node = fn_proto->params.at(param_decl_i);2144 AstNode *param_node = fn_proto->params.at(param_decl_i);
2216 assert(param_node->type == NodeTypeParamDecl);2145 assert(param_node->type == NodeTypeParamDecl);
...@@ -2218,7 +2147,7 @@ static void do_code_gen(CodeGen *g) {...@@ -2218,7 +2147,7 @@ static void do_code_gen(CodeGen *g) {
2218 continue;2147 continue;
2219 AstNode *type_node = param_node->data.param_decl.type;2148 AstNode *type_node = param_node->data.param_decl.type;
2220 TypeTableEntry *param_type = fn_proto_type_from_type_node(g, type_node);2149 TypeTableEntry *param_type = fn_proto_type_from_type_node(g, type_node);
2221 LLVMValueRef argument_val = LLVMGetParam(fn, gen_param_index);2150 LLVMValueRef argument_val = LLVMGetParam(fn_table_entry->fn_value, gen_param_index);
2222 bool param_is_noalias = param_node->data.param_decl.is_noalias;2151 bool param_is_noalias = param_node->data.param_decl.is_noalias;
2223 if (param_type->id == TypeTableEntryIdPointer && param_is_noalias) {2152 if (param_type->id == TypeTableEntryIdPointer && param_is_noalias) {
2224 LLVMAddAttribute(argument_val, LLVMNoAliasAttribute);2153 LLVMAddAttribute(argument_val, LLVMNoAliasAttribute);
...@@ -2230,7 +2159,6 @@ static void do_code_gen(CodeGen *g) {...@@ -2230,7 +2159,6 @@ static void do_code_gen(CodeGen *g) {
2230 gen_param_index += 1;2159 gen_param_index += 1;
2231 }2160 }
22322161
2233 fn_table_entry->fn_value = fn;
2234 }2162 }
22352163
2236 // Generate function definitions.2164 // Generate function definitions.
...@@ -2245,22 +2173,9 @@ static void do_code_gen(CodeGen *g) {...@@ -2245,22 +2173,9 @@ static void do_code_gen(CodeGen *g) {
2245 assert(proto_node->type == NodeTypeFnProto);2173 assert(proto_node->type == NodeTypeFnProto);
2246 AstNodeFnProto *fn_proto = &proto_node->data.fn_proto;2174 AstNodeFnProto *fn_proto = &proto_node->data.fn_proto;
22472175
2248 // Add debug info.
2249 unsigned line_number = fn_def_node->line + 1;
2250 unsigned scope_line = line_number;
2251 bool is_definition = true;
2252 unsigned flags = 0;
2253 bool is_optimized = g->build_type == CodeGenBuildTypeRelease;
2254 LLVMZigDISubprogram *subprogram = LLVMZigCreateFunction(g->dbuilder,
2255 import->block_context->di_scope, buf_ptr(&fn_table_entry->symbol_name), "",
2256 import->di_file, line_number,
2257 create_di_function_type(g, fn_proto, import->di_file), fn_table_entry->internal_linkage,
2258 is_definition, scope_line, flags, is_optimized, fn);
2259
2260 LLVMBasicBlockRef entry_block = LLVMAppendBasicBlock(fn, "entry");2176 LLVMBasicBlockRef entry_block = LLVMAppendBasicBlock(fn, "entry");
2261 LLVMPositionBuilderAtEnd(g->builder, entry_block);2177 LLVMPositionBuilderAtEnd(g->builder, entry_block);
22622178
2263 fn_def_node->data.fn_def.block_context->di_scope = LLVMZigSubprogramToScope(subprogram);
22642179
2265 AstNode *body_node = fn_def_node->data.fn_def.body;2180 AstNode *body_node = fn_def_node->data.fn_def.body;
2266 build_label_blocks(g, body_node);2181 build_label_blocks(g, body_node);
src/zig_llvm.cpp+5
...@@ -388,6 +388,11 @@ LLVMZigDIScope *LLVMZigSubprogramToScope(LLVMZigDISubprogram *subprogram) {...@@ -388,6 +388,11 @@ LLVMZigDIScope *LLVMZigSubprogramToScope(LLVMZigDISubprogram *subprogram) {
388 return reinterpret_cast<LLVMZigDIScope*>(scope);388 return reinterpret_cast<LLVMZigDIScope*>(scope);
389}389}
390390
391LLVMZigDIType *LLVMZigSubroutineToType(LLVMZigDISubroutineType *subrtype) {
392 DIType *di_type = reinterpret_cast<DISubroutineType*>(subrtype);
393 return reinterpret_cast<LLVMZigDIType*>(di_type);
394}
395
391LLVMZigDIScope *LLVMZigTypeToScope(LLVMZigDIType *type) {396LLVMZigDIScope *LLVMZigTypeToScope(LLVMZigDIType *type) {
392 DIScope *scope = reinterpret_cast<DIType*>(type);397 DIScope *scope = reinterpret_cast<DIType*>(type);
393 return reinterpret_cast<LLVMZigDIScope*>(scope);398 return reinterpret_cast<LLVMZigDIScope*>(scope);
src/zig_llvm.hpp+1
...@@ -101,6 +101,7 @@ LLVMZigDIScope *LLVMZigCompileUnitToScope(LLVMZigDICompileUnit *compile_unit);...@@ -101,6 +101,7 @@ LLVMZigDIScope *LLVMZigCompileUnitToScope(LLVMZigDICompileUnit *compile_unit);
101LLVMZigDIScope *LLVMZigFileToScope(LLVMZigDIFile *difile);101LLVMZigDIScope *LLVMZigFileToScope(LLVMZigDIFile *difile);
102LLVMZigDIScope *LLVMZigSubprogramToScope(LLVMZigDISubprogram *subprogram);102LLVMZigDIScope *LLVMZigSubprogramToScope(LLVMZigDISubprogram *subprogram);
103LLVMZigDIScope *LLVMZigTypeToScope(LLVMZigDIType *type);103LLVMZigDIScope *LLVMZigTypeToScope(LLVMZigDIType *type);
104LLVMZigDIType *LLVMZigSubroutineToType(LLVMZigDISubroutineType *subrtype);
104105
105LLVMZigDILocalVariable *LLVMZigCreateLocalVariable(LLVMZigDIBuilder *dbuilder, unsigned tag,106LLVMZigDILocalVariable *LLVMZigCreateLocalVariable(LLVMZigDIBuilder *dbuilder, unsigned tag,
106 LLVMZigDIScope *scope, const char *name, LLVMZigDIFile *file, unsigned line_no,107 LLVMZigDIScope *scope, const char *name, LLVMZigDIFile *file, unsigned line_no,
test/run_tests.cpp-4
...@@ -1296,10 +1296,6 @@ fn f() => {...@@ -1296,10 +1296,6 @@ fn f() => {
1296fn f(a : unreachable) => {}1296fn f(a : unreachable) => {}
1297 )SOURCE", 1, ".tmp_source.zig:2:10: error: parameter of type 'unreachable' not allowed");1297 )SOURCE", 1, ".tmp_source.zig:2:10: error: parameter of type 'unreachable' not allowed");
12981298
1299 add_compile_fail_case("exporting a void parameter", R"SOURCE(
1300export fn f(a : void) => {}
1301 )SOURCE", 1, ".tmp_source.zig:2:17: error: parameter of type 'void' not allowed on exported functions");
1302
1303 add_compile_fail_case("unused label", R"SOURCE(1299 add_compile_fail_case("unused label", R"SOURCE(
1304fn f() => {1300fn f() => {
1305a_label:1301a_label: