authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-01-12 03:15:06-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-01-12 03:15:06-05:00
logd7847053531c3352db8355e21e54b102958cbb8a
treeb360eeecaa1b6624c268054bb2a7d79d4678d591
parent76b1cbc2ea50be928608b80bdd8ab25cd1b964f3

IR: implement macro for function aliasing function pointer


10 files changed, 176 insertions(+), 139 deletions(-)

src/analyze.cpp+56-37
...@@ -193,7 +193,7 @@ Scope *create_loop_scope(AstNode *node, Scope *parent) {...@@ -193,7 +193,7 @@ Scope *create_loop_scope(AstNode *node, Scope *parent) {
193}193}
194194
195ScopeFnDef *create_fndef_scope(AstNode *node, Scope *parent, FnTableEntry *fn_entry) {195ScopeFnDef *create_fndef_scope(AstNode *node, Scope *parent, FnTableEntry *fn_entry) {
196 assert(node->type == NodeTypeFnDef);196 assert(!node || node->type == NodeTypeFnDef);
197 ScopeFnDef *scope = allocate<ScopeFnDef>(1);197 ScopeFnDef *scope = allocate<ScopeFnDef>(1);
198 init_scope(&scope->base, ScopeIdFnDef, node, parent);198 init_scope(&scope->base, ScopeIdFnDef, node, parent);
199 scope->fn_entry = fn_entry;199 scope->fn_entry = fn_entry;
...@@ -2341,31 +2341,20 @@ bool type_is_codegen_pointer(TypeTableEntry *type) {...@@ -2341,31 +2341,20 @@ bool type_is_codegen_pointer(TypeTableEntry *type) {
2341AstNode *get_param_decl_node(FnTableEntry *fn_entry, size_t index) {2341AstNode *get_param_decl_node(FnTableEntry *fn_entry, size_t index) {
2342 if (fn_entry->param_source_nodes)2342 if (fn_entry->param_source_nodes)
2343 return fn_entry->param_source_nodes[index];2343 return fn_entry->param_source_nodes[index];
2344 else2344 else if (fn_entry->proto_node)
2345 return fn_entry->proto_node->data.fn_proto.params.at(index);2345 return fn_entry->proto_node->data.fn_proto.params.at(index);
2346 else
2347 return nullptr;
2346}2348}
23472349
2348static void analyze_fn_body(CodeGen *g, FnTableEntry *fn_table_entry) {2350void define_local_param_variables(CodeGen *g, FnTableEntry *fn_table_entry, VariableTableEntry **arg_vars) {
2349 assert(fn_table_entry->anal_state != FnAnalStateProbing);
2350 if (fn_table_entry->anal_state != FnAnalStateReady)
2351 return;
2352
2353 fn_table_entry->anal_state = FnAnalStateProbing;
2354
2355 AstNodeFnProto *fn_proto = &fn_table_entry->proto_node->data.fn_proto;
2356
2357 assert(fn_table_entry->fndef_scope);
2358 if (!fn_table_entry->child_scope)
2359 fn_table_entry->child_scope = &fn_table_entry->fndef_scope->base;
2360
2361 // define local variables for parameters
2362 TypeTableEntry *fn_type = fn_table_entry->type_entry;2351 TypeTableEntry *fn_type = fn_table_entry->type_entry;
2363 assert(!fn_type->data.fn.is_generic);2352 assert(!fn_type->data.fn.is_generic);
2364 FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id;2353 FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id;
2365 for (size_t i = 0; i < fn_type_id->param_count; i += 1) {2354 for (size_t i = 0; i < fn_type_id->param_count; i += 1) {
2366 FnTypeParamInfo *param_info = &fn_type_id->param_info[i];2355 FnTypeParamInfo *param_info = &fn_type_id->param_info[i];
2367 AstNode *param_decl_node = get_param_decl_node(fn_table_entry, i);2356 AstNode *param_decl_node = get_param_decl_node(fn_table_entry, i);
2368 AstNodeParamDecl *param_decl = &param_decl_node->data.param_decl;2357 Buf *param_name = param_decl_node ? param_decl_node->data.param_decl.name : buf_sprintf("arg%zu", i);
23692358
2370 TypeTableEntry *param_type = param_info->type;2359 TypeTableEntry *param_type = param_info->type;
2371 bool is_noalias = param_info->is_noalias;2360 bool is_noalias = param_info->is_noalias;
...@@ -2380,7 +2369,7 @@ static void analyze_fn_body(CodeGen *g, FnTableEntry *fn_table_entry) {...@@ -2380,7 +2369,7 @@ static void analyze_fn_body(CodeGen *g, FnTableEntry *fn_table_entry) {
2380 }2369 }
23812370
2382 VariableTableEntry *var = add_variable(g, param_decl_node, fn_table_entry->child_scope,2371 VariableTableEntry *var = add_variable(g, param_decl_node, fn_table_entry->child_scope,
2383 param_decl->name, true, create_const_runtime(param_type));2372 param_name, true, create_const_runtime(param_type));
2384 var->src_arg_index = i;2373 var->src_arg_index = i;
2385 fn_table_entry->child_scope = var->child_scope;2374 fn_table_entry->child_scope = var->child_scope;
23862375
...@@ -2391,30 +2380,20 @@ static void analyze_fn_body(CodeGen *g, FnTableEntry *fn_table_entry) {...@@ -2391,30 +2380,20 @@ static void analyze_fn_body(CodeGen *g, FnTableEntry *fn_table_entry) {
2391 if (fn_type->data.fn.gen_param_info) {2380 if (fn_type->data.fn.gen_param_info) {
2392 var->gen_arg_index = fn_type->data.fn.gen_param_info[i].gen_index;2381 var->gen_arg_index = fn_type->data.fn.gen_param_info[i].gen_index;
2393 }2382 }
2394 }
2395
2396 TypeTableEntry *expected_type = fn_type_id->return_type;
23972383
2398 if (fn_type_id->is_extern && handle_is_ptr(expected_type)) {2384 if (arg_vars) {
2399 add_node_error(g, fn_proto->return_type,2385 arg_vars[i] = var;
2400 buf_sprintf("byvalue types not yet supported on extern function return values"));2386 }
2401 }2387 }
2388}
24022389
2403 ir_gen_fn(g, fn_table_entry);2390void analyze_fn_ir(CodeGen *g, FnTableEntry *fn_table_entry, AstNode *return_type_node) {
2404 if (fn_table_entry->ir_executable.invalid) {2391 TypeTableEntry *fn_type = fn_table_entry->type_entry;
2405 fn_table_entry->anal_state = FnAnalStateInvalid;2392 assert(!fn_type->data.fn.is_generic);
2406 return;2393 FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id;
2407 }
2408 if (g->verbose) {
2409 fprintf(stderr, "\n");
2410 ast_render(stderr, fn_table_entry->fn_def_node, 4);
2411 fprintf(stderr, "\n{ // (IR)\n");
2412 ir_print(stderr, &fn_table_entry->ir_executable, 4);
2413 fprintf(stderr, "}\n");
2414 }
24152394
2416 TypeTableEntry *block_return_type = ir_analyze(g, &fn_table_entry->ir_executable,2395 TypeTableEntry *block_return_type = ir_analyze(g, &fn_table_entry->ir_executable,
2417 &fn_table_entry->analyzed_executable, expected_type, fn_proto->return_type);2396 &fn_table_entry->analyzed_executable, fn_type_id->return_type, return_type_node);
2418 fn_table_entry->implicit_return_type = block_return_type;2397 fn_table_entry->implicit_return_type = block_return_type;
24192398
2420 if (block_return_type->id == TypeTableEntryIdInvalid ||2399 if (block_return_type->id == TypeTableEntryIdInvalid ||
...@@ -2434,6 +2413,46 @@ static void analyze_fn_body(CodeGen *g, FnTableEntry *fn_table_entry) {...@@ -2434,6 +2413,46 @@ static void analyze_fn_body(CodeGen *g, FnTableEntry *fn_table_entry) {
2434 fn_table_entry->anal_state = FnAnalStateComplete;2413 fn_table_entry->anal_state = FnAnalStateComplete;
2435}2414}
24362415
2416static void analyze_fn_body(CodeGen *g, FnTableEntry *fn_table_entry) {
2417 assert(fn_table_entry->anal_state != FnAnalStateProbing);
2418 if (fn_table_entry->anal_state != FnAnalStateReady)
2419 return;
2420
2421 fn_table_entry->anal_state = FnAnalStateProbing;
2422
2423 AstNode *return_type_node = fn_table_entry->proto_node->data.fn_proto.return_type;
2424
2425 assert(fn_table_entry->fndef_scope);
2426 if (!fn_table_entry->child_scope)
2427 fn_table_entry->child_scope = &fn_table_entry->fndef_scope->base;
2428
2429 define_local_param_variables(g, fn_table_entry, nullptr);
2430
2431 TypeTableEntry *fn_type = fn_table_entry->type_entry;
2432 assert(!fn_type->data.fn.is_generic);
2433 FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id;
2434
2435 if (fn_type_id->is_extern && handle_is_ptr(fn_type_id->return_type)) {
2436 add_node_error(g, return_type_node,
2437 buf_sprintf("byvalue types not yet supported on extern function return values"));
2438 }
2439
2440 ir_gen_fn(g, fn_table_entry);
2441 if (fn_table_entry->ir_executable.invalid) {
2442 fn_table_entry->anal_state = FnAnalStateInvalid;
2443 return;
2444 }
2445 if (g->verbose) {
2446 fprintf(stderr, "\n");
2447 ast_render(stderr, fn_table_entry->fn_def_node, 4);
2448 fprintf(stderr, "\n{ // (IR)\n");
2449 ir_print(stderr, &fn_table_entry->ir_executable, 4);
2450 fprintf(stderr, "}\n");
2451 }
2452
2453 analyze_fn_ir(g, fn_table_entry, return_type_node);
2454}
2455
2437static void add_symbols_from_import(CodeGen *g, AstNode *dst_use_node) {2456static void add_symbols_from_import(CodeGen *g, AstNode *dst_use_node) {
2438 IrInstruction *use_target_value = dst_use_node->data.use.value;2457 IrInstruction *use_target_value = dst_use_node->data.use.value;
2439 if (use_target_value->value.type->id == TypeTableEntryIdInvalid) {2458 if (use_target_value->value.type->id == TypeTableEntryIdInvalid) {
src/analyze.hpp+2
...@@ -83,6 +83,8 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b);...@@ -83,6 +83,8 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b);
83void eval_min_max_value(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val, bool is_max);83void eval_min_max_value(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val, bool is_max);
8484
85void render_const_value(Buf *buf, ConstExprValue *const_val);85void render_const_value(Buf *buf, ConstExprValue *const_val);
86void define_local_param_variables(CodeGen *g, FnTableEntry *fn_table_entry, VariableTableEntry **arg_vars);
87void analyze_fn_ir(CodeGen *g, FnTableEntry *fn_table_entry, AstNode *return_type_node);
8688
87ScopeBlock *create_block_scope(AstNode *node, Scope *parent);89ScopeBlock *create_block_scope(AstNode *node, Scope *parent);
88ScopeDefer *create_defer_scope(AstNode *node, Scope *parent);90ScopeDefer *create_defer_scope(AstNode *node, Scope *parent);
src/ast_render.cpp+19-14
...@@ -908,7 +908,8 @@ static void ast_render_tld_fn(AstRender *ar, Buf *name, TldFn *tld_fn) {...@@ -908,7 +908,8 @@ static void ast_render_tld_fn(AstRender *ar, Buf *name, TldFn *tld_fn) {
908 if (param_info->is_noalias) {908 if (param_info->is_noalias) {
909 fprintf(ar->f, "noalias ");909 fprintf(ar->f, "noalias ");
910 }910 }
911 fprintf(ar->f, "%s: %s", buf_ptr(tld_fn->fn_entry->param_names[i]), buf_ptr(&param_info->type->name));911 Buf *param_name = tld_fn->fn_entry->param_names ? tld_fn->fn_entry->param_names[i] : buf_sprintf("arg%zu", i);
912 fprintf(ar->f, "%s: %s", buf_ptr(param_name), buf_ptr(&param_info->type->name));
912 }913 }
913 if (fn_type_id->return_type->id == TypeTableEntryIdVoid) {914 if (fn_type_id->return_type->id == TypeTableEntryIdVoid) {
914 fprintf(ar->f, ");\n");915 fprintf(ar->f, ");\n");
...@@ -947,24 +948,28 @@ static void ast_render_tld_var(AstRender *ar, Buf *name, TldVar *tld_var) {...@@ -947,24 +948,28 @@ static void ast_render_tld_var(AstRender *ar, Buf *name, TldVar *tld_var) {
947 if (type_entry->id == TypeTableEntryIdStruct) {948 if (type_entry->id == TypeTableEntryIdStruct) {
948 const char *extern_str = extern_string(type_entry->data.structure.is_extern);949 const char *extern_str = extern_string(type_entry->data.structure.is_extern);
949 fprintf(ar->f, "%sstruct {\n", extern_str);950 fprintf(ar->f, "%sstruct {\n", extern_str);
950 for (size_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) {951 if (type_entry->data.structure.complete) {
951 TypeStructField *field = &type_entry->data.structure.fields[i];952 for (size_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) {
952 fprintf(ar->f, " ");953 TypeStructField *field = &type_entry->data.structure.fields[i];
953 print_symbol(ar, field->name);954 fprintf(ar->f, " ");
954 fprintf(ar->f, ": %s,\n", buf_ptr(&field->type_entry->name));955 print_symbol(ar, field->name);
956 fprintf(ar->f, ": %s,\n", buf_ptr(&field->type_entry->name));
957 }
955 }958 }
956 fprintf(ar->f, "}");959 fprintf(ar->f, "}");
957 } else if (type_entry->id == TypeTableEntryIdEnum) {960 } else if (type_entry->id == TypeTableEntryIdEnum) {
958 const char *extern_str = extern_string(type_entry->data.enumeration.is_extern);961 const char *extern_str = extern_string(type_entry->data.enumeration.is_extern);
959 fprintf(ar->f, "%senum {\n", extern_str);962 fprintf(ar->f, "%senum {\n", extern_str);
960 for (size_t i = 0; i < type_entry->data.enumeration.src_field_count; i += 1) {963 if (type_entry->data.enumeration.complete) {
961 TypeEnumField *field = &type_entry->data.enumeration.fields[i];964 for (size_t i = 0; i < type_entry->data.enumeration.src_field_count; i += 1) {
962 fprintf(ar->f, " ");965 TypeEnumField *field = &type_entry->data.enumeration.fields[i];
963 print_symbol(ar, field->name);966 fprintf(ar->f, " ");
964 if (field->type_entry->id == TypeTableEntryIdVoid) {967 print_symbol(ar, field->name);
965 fprintf(ar->f, ",\n");968 if (field->type_entry->id == TypeTableEntryIdVoid) {
966 } else {969 fprintf(ar->f, ",\n");
967 fprintf(ar->f, ": %s,\n", buf_ptr(&field->type_entry->name));970 } else {
971 fprintf(ar->f, ": %s,\n", buf_ptr(&field->type_entry->name));
972 }
968 }973 }
969 }974 }
970 fprintf(ar->f, "}");975 fprintf(ar->f, "}");
src/codegen.cpp+10-5
...@@ -287,6 +287,8 @@ static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) {...@@ -287,6 +287,8 @@ static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) {
287 assert(scope->parent);287 assert(scope->parent);
288 ScopeFnDef *fn_scope = (ScopeFnDef *)scope;288 ScopeFnDef *fn_scope = (ScopeFnDef *)scope;
289 FnTableEntry *fn_table_entry = fn_scope->fn_entry;289 FnTableEntry *fn_table_entry = fn_scope->fn_entry;
290 if (!fn_table_entry->proto_node)
291 return get_di_scope(g, scope->parent);
290 unsigned line_number = fn_table_entry->proto_node->line + 1;292 unsigned line_number = fn_table_entry->proto_node->line + 1;
291 unsigned scope_line = line_number;293 unsigned scope_line = line_number;
292 bool is_definition = fn_table_entry->fn_def_node != nullptr;294 bool is_definition = fn_table_entry->fn_def_node != nullptr;
...@@ -2808,7 +2810,6 @@ static void do_code_gen(CodeGen *g) {...@@ -2808,7 +2810,6 @@ static void do_code_gen(CodeGen *g) {
2808 continue;2810 continue;
28092811
2810 assert(var->decl_node);2812 assert(var->decl_node);
2811 assert(var->decl_node->type == NodeTypeVariableDeclaration);
28122813
2813 LLVMValueRef global_value;2814 LLVMValueRef global_value;
2814 if (var->is_extern) {2815 if (var->is_extern) {
...@@ -3033,9 +3034,11 @@ static void do_code_gen(CodeGen *g) {...@@ -3033,9 +3034,11 @@ static void do_code_gen(CodeGen *g) {
3033 unsigned align_bytes = ZigLLVMGetPrefTypeAlignment(g->target_data_ref, var->value.type->type_ref);3034 unsigned align_bytes = ZigLLVMGetPrefTypeAlignment(g->target_data_ref, var->value.type->type_ref);
3034 LLVMSetAlignment(var->value_ref, align_bytes);3035 LLVMSetAlignment(var->value_ref, align_bytes);
3035 }3036 }
3036 var->di_loc_var = ZigLLVMCreateParameterVariable(g->dbuilder, get_di_scope(g, var->parent_scope),3037 if (var->decl_node) {
3037 buf_ptr(&var->name), import->di_file, var->decl_node->line + 1,3038 var->di_loc_var = ZigLLVMCreateParameterVariable(g->dbuilder, get_di_scope(g, var->parent_scope),
3038 gen_type->di_type, !g->strip_debug_symbols, 0, var->gen_arg_index + 1);3039 buf_ptr(&var->name), import->di_file, var->decl_node->line + 1,
3040 gen_type->di_type, !g->strip_debug_symbols, 0, var->gen_arg_index + 1);
3041 }
30393042
3040 }3043 }
3041 }3044 }
...@@ -3062,7 +3065,9 @@ static void do_code_gen(CodeGen *g) {...@@ -3062,7 +3065,9 @@ static void do_code_gen(CodeGen *g) {
3062 LLVMBuildStore(g->builder, LLVMGetParam(fn, variable->gen_arg_index), variable->value_ref);3065 LLVMBuildStore(g->builder, LLVMGetParam(fn, variable->gen_arg_index), variable->value_ref);
3063 }3066 }
30643067
3065 gen_var_debug_decl(g, variable);3068 if (variable->decl_node) {
3069 gen_var_debug_decl(g, variable);
3070 }
3066 }3071 }
30673072
3068 ir_render(g, fn_table_entry);3073 ir_render(g, fn_table_entry);
src/ir.cpp+63-3
...@@ -500,7 +500,6 @@ static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_no...@@ -500,7 +500,6 @@ static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_no
500500
501template<typename T>501template<typename T>
502static T *ir_build_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) {502static T *ir_build_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) {
503 assert(source_node);
504 T *special_instruction = ir_create_instruction<T>(irb, scope, source_node);503 T *special_instruction = ir_create_instruction<T>(irb, scope, source_node);
505 ir_instruction_append(irb->current_basic_block, &special_instruction->base);504 ir_instruction_append(irb->current_basic_block, &special_instruction->base);
506 return special_instruction;505 return special_instruction;
...@@ -10120,7 +10119,7 @@ static TypeTableEntry *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruc...@@ -10120,7 +10119,7 @@ static TypeTableEntry *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruc
10120 find_libc_include_path(ira->codegen);10119 find_libc_include_path(ira->codegen);
1012110120
10122 ImportTableEntry *child_import = allocate<ImportTableEntry>(1);10121 ImportTableEntry *child_import = allocate<ImportTableEntry>(1);
10123 child_import->decls_scope = create_decls_scope(child_import->root, nullptr, nullptr, child_import);10122 child_import->decls_scope = create_decls_scope(node, nullptr, nullptr, child_import);
10124 child_import->c_import_node = node;10123 child_import->c_import_node = node;
1012510124
10126 ZigList<ErrorMsg *> errors = {0};10125 ZigList<ErrorMsg *> errors = {0};
...@@ -10143,7 +10142,7 @@ static TypeTableEntry *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruc...@@ -10143,7 +10142,7 @@ static TypeTableEntry *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruc
10143 if (ira->codegen->verbose) {10142 if (ira->codegen->verbose) {
10144 fprintf(stderr, "\nC imports:\n");10143 fprintf(stderr, "\nC imports:\n");
10145 fprintf(stderr, "-----------\n");10144 fprintf(stderr, "-----------\n");
10146 ir_print_decls(stderr, child_import);10145 ast_render_decls(stderr, 4, child_import);
10147 }10146 }
1014810147
10149 // TODO to get fewer false negatives on this, we would need to track this value in10148 // TODO to get fewer false negatives on this, we would need to track this value in
...@@ -11546,3 +11545,64 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -11546,3 +11545,64 @@ bool ir_has_side_effects(IrInstruction *instruction) {
11546 zig_unreachable();11545 zig_unreachable();
11547}11546}
1154811547
11548FnTableEntry *ir_create_inline_fn(CodeGen *codegen, Buf *fn_name, VariableTableEntry *var, Scope *parent_scope) {
11549 FnTableEntry *fn_entry = create_fn_raw(FnInlineAuto, true);
11550 buf_init_from_buf(&fn_entry->symbol_name, fn_name);
11551
11552 fn_entry->fndef_scope = create_fndef_scope(nullptr, parent_scope, fn_entry);
11553 fn_entry->child_scope = &fn_entry->fndef_scope->base;
11554
11555 assert(var->value.type->id == TypeTableEntryIdMaybe);
11556 TypeTableEntry *src_fn_type = var->value.type->data.maybe.child_type;
11557 assert(src_fn_type->id == TypeTableEntryIdFn);
11558
11559 FnTypeId new_fn_type = src_fn_type->data.fn.fn_type_id;
11560 new_fn_type.is_extern = false;
11561
11562 fn_entry->type_entry = get_fn_type(codegen, &new_fn_type);
11563
11564 IrBuilder ir_builder = {0};
11565 IrBuilder *irb = &ir_builder;
11566
11567 irb->codegen = codegen;
11568 irb->exec = &fn_entry->ir_executable;
11569
11570 AstNode *source_node = parent_scope->source_node;
11571
11572 size_t arg_count = fn_entry->type_entry->data.fn.fn_type_id.param_count;
11573 IrInstruction **args = allocate<IrInstruction *>(arg_count);
11574 VariableTableEntry **arg_vars = allocate<VariableTableEntry *>(arg_count);
11575
11576 define_local_param_variables(codegen, fn_entry, arg_vars);
11577 Scope *scope = fn_entry->child_scope;
11578
11579 irb->current_basic_block = ir_build_basic_block(irb, scope, "Entry");
11580 // Entry block gets a reference because we enter it to begin.
11581 ir_ref_bb(irb->current_basic_block);
11582
11583 IrInstruction *maybe_fn_ptr = ir_build_var_ptr(irb, scope, source_node, var, true);
11584 IrInstruction *unwrapped_fn_ptr = ir_build_unwrap_maybe(irb, scope, source_node, maybe_fn_ptr, true);
11585 IrInstruction *fn_ref_instruction = ir_build_load_ptr(irb, scope, source_node, unwrapped_fn_ptr);
11586
11587 for (size_t i = 0; i < arg_count; i += 1) {
11588 IrInstruction *var_ptr_instruction = ir_build_var_ptr(irb, scope, source_node, arg_vars[i], true);
11589 args[i] = ir_build_load_ptr(irb, scope, source_node, var_ptr_instruction);
11590 }
11591
11592 IrInstruction *call_instruction = ir_build_call(irb, scope, source_node, nullptr, fn_ref_instruction,
11593 arg_count, args, false);
11594 ir_build_return(irb, scope, source_node, call_instruction);
11595
11596 if (codegen->verbose) {
11597 fprintf(stderr, "{\n");
11598 ir_print(stderr, &fn_entry->ir_executable, 4);
11599 fprintf(stderr, "}\n");
11600 }
11601
11602 analyze_fn_ir(codegen, fn_entry, nullptr);
11603
11604 codegen->fn_defs.append(fn_entry);
11605
11606 return fn_entry;
11607}
11608
src/ir.hpp+2
...@@ -24,4 +24,6 @@ TypeTableEntry *ir_analyze(CodeGen *g, IrExecutable *old_executable, IrExecutabl...@@ -24,4 +24,6 @@ TypeTableEntry *ir_analyze(CodeGen *g, IrExecutable *old_executable, IrExecutabl
24bool ir_has_side_effects(IrInstruction *instruction);24bool ir_has_side_effects(IrInstruction *instruction);
25ConstExprValue *const_ptr_pointee(ConstExprValue *const_val);25ConstExprValue *const_ptr_pointee(ConstExprValue *const_val);
2626
27FnTableEntry *ir_create_inline_fn(CodeGen *codegen, Buf *fn_name, VariableTableEntry *var, Scope *parent_scope);
28
27#endif29#endif
src/ir_print.cpp-64
...@@ -1093,67 +1093,3 @@ void ir_print(FILE *f, IrExecutable *executable, int indent_size) {...@@ -1093,67 +1093,3 @@ void ir_print(FILE *f, IrExecutable *executable, int indent_size) {
1093 }1093 }
1094 }1094 }
1095}1095}
1096
1097static void print_tld_var(IrPrint *irp, TldVar *tld_var) {
1098 const char *const_or_var = tld_var->var->src_is_const ? "const" : "var";
1099 fprintf(irp->f, "%s %s", const_or_var, buf_ptr(tld_var->base.name));
1100 bool omit_type = (tld_var->var->value.type->id == TypeTableEntryIdNumLitFloat ||
1101 tld_var->var->value.type->id == TypeTableEntryIdNumLitInt);
1102 if (!omit_type) {
1103 fprintf(irp->f, ": %s", buf_ptr(&tld_var->var->value.type->name));
1104 }
1105 if (tld_var->var->value.special != ConstValSpecialRuntime) {
1106 fprintf(irp->f, " = ");
1107 ir_print_const_value(irp, &tld_var->var->value);
1108 }
1109 fprintf(irp->f, ";\n");
1110}
1111
1112static void print_tld_fn(IrPrint *irp, TldFn *tld_fn) {
1113 fprintf(irp->f, "// %s = TODO (function)\n", buf_ptr(tld_fn->base.name));
1114}
1115
1116static void print_tld_container(IrPrint *irp, TldContainer *tld_container) {
1117 fprintf(irp->f, "// %s = TODO (container)\n", buf_ptr(tld_container->base.name));
1118}
1119
1120static void print_tld_typedef(IrPrint *irp, TldTypeDef *tld_typedef) {
1121 fprintf(irp->f, "// %s = TODO (typedef)\n", buf_ptr(tld_typedef->base.name));
1122}
1123
1124void ir_print_decls(FILE *f, ImportTableEntry *import) {
1125 IrPrint ir_print = {};
1126 IrPrint *irp = &ir_print;
1127 irp->f = f;
1128 irp->indent = 0;
1129 irp->indent_size = 2;
1130
1131 auto it = import->decls_scope->decl_table.entry_iterator();
1132 for (;;) {
1133 auto *entry = it.next();
1134 if (!entry)
1135 break;
1136
1137 Tld *tld = entry->value;
1138 if (!buf_eql_buf(entry->key, tld->name)) {
1139 fprintf(f, "// alias: %s = %s\n", buf_ptr(entry->key), buf_ptr(tld->name));
1140 continue;
1141 }
1142
1143 switch (tld->id) {
1144 case TldIdVar:
1145 print_tld_var(irp, (TldVar *)tld);
1146 continue;
1147 case TldIdFn:
1148 print_tld_fn(irp, (TldFn *)tld);
1149 continue;
1150 case TldIdContainer:
1151 print_tld_container(irp, (TldContainer *)tld);
1152 continue;
1153 case TldIdTypeDef:
1154 print_tld_typedef(irp, (TldTypeDef *)tld);
1155 continue;
1156 }
1157 zig_unreachable();
1158 }
1159}
src/ir_print.hpp-3
...@@ -14,7 +14,4 @@...@@ -14,7 +14,4 @@
1414
15void ir_print(FILE *f, IrExecutable *executable, int indent_size);15void ir_print(FILE *f, IrExecutable *executable, int indent_size);
1616
17void ir_print_decls(FILE *f, ImportTableEntry *import);
18
19
20#endif17#endif
src/parseh.cpp+16-8
...@@ -5,14 +5,15 @@...@@ -5,14 +5,15 @@
5 * See http://opensource.org/licenses/MIT5 * See http://opensource.org/licenses/MIT
6 */6 */
77
8#include "parseh.hpp"8#include "all_types.hpp"
9#include "analyze.hpp"
10#include "c_tokenizer.hpp"
9#include "config.h"11#include "config.h"
10#include "os.hpp"
11#include "error.hpp"12#include "error.hpp"
13#include "ir.hpp"
14#include "os.hpp"
15#include "parseh.hpp"
12#include "parser.hpp"16#include "parser.hpp"
13#include "all_types.hpp"
14#include "c_tokenizer.hpp"
15#include "analyze.hpp"
1617
17#include <clang/Frontend/ASTUnit.h>18#include <clang/Frontend/ASTUnit.h>
18#include <clang/Frontend/CompilerInstance.h>19#include <clang/Frontend/CompilerInstance.h>
...@@ -133,6 +134,13 @@ static void parseh_init_tld(Context *c, Tld *tld, TldId id, Buf *name) {...@@ -133,6 +134,13 @@ static void parseh_init_tld(Context *c, Tld *tld, TldId id, Buf *name) {
133 tld->resolution = TldResolutionOk;134 tld->resolution = TldResolutionOk;
134}135}
135136
137static Tld *create_inline_fn_tld(Context *c, Buf *fn_name, TldVar *tld_var) {
138 TldFn *tld_fn = allocate<TldFn>(1);
139 parseh_init_tld(c, &tld_fn->base, TldIdFn, fn_name);
140 tld_fn->fn_entry = ir_create_inline_fn(c->codegen, fn_name, tld_var->var, &c->import->decls_scope->base);
141 return &tld_fn->base;
142}
143
136static TldVar *create_global_var(Context *c, Buf *name, ConstExprValue *var_value, bool is_const) {144static TldVar *create_global_var(Context *c, Buf *name, ConstExprValue *var_value, bool is_const) {
137 auto entry = c->import->decls_scope->decl_table.maybe_get(name);145 auto entry = c->import->decls_scope->decl_table.maybe_get(name);
138 if (entry) {146 if (entry) {
...@@ -143,6 +151,7 @@ static TldVar *create_global_var(Context *c, Buf *name, ConstExprValue *var_valu...@@ -143,6 +151,7 @@ static TldVar *create_global_var(Context *c, Buf *name, ConstExprValue *var_valu
143 TldVar *tld_var = allocate<TldVar>(1);151 TldVar *tld_var = allocate<TldVar>(1);
144 parseh_init_tld(c, &tld_var->base, TldIdVar, name);152 parseh_init_tld(c, &tld_var->base, TldIdVar, name);
145 tld_var->var = add_variable(c->codegen, c->source_node, &c->import->decls_scope->base, name, is_const, var_value);153 tld_var->var = add_variable(c->codegen, c->source_node, &c->import->decls_scope->base, name, is_const, var_value);
154 c->codegen->global_vars.append(tld_var->var);
146 return tld_var;155 return tld_var;
147}156}
148157
...@@ -1229,9 +1238,8 @@ static void process_symbol_macros(Context *c) {...@@ -1229,9 +1238,8 @@ static void process_symbol_macros(Context *c) {
1229 if (var_type->id == TypeTableEntryIdMaybe && !tld_var->var->src_is_const) {1238 if (var_type->id == TypeTableEntryIdMaybe && !tld_var->var->src_is_const) {
1230 TypeTableEntry *child_type = var_type->data.maybe.child_type;1239 TypeTableEntry *child_type = var_type->data.maybe.child_type;
1231 if (child_type->id == TypeTableEntryIdFn) {1240 if (child_type->id == TypeTableEntryIdFn) {
1232 zig_panic("TODO macro alias of function pointer in .h file");1241 Tld *tld = create_inline_fn_tld(c, ms.name, tld_var);
1233 //Tld *fn_tld = create_inline_fn_alias(c, ms.name, tld_var->var);1242 c->macro_table.put(ms.name, tld);
1234 //c->macro_table.put(ms.name, fn_tld);
1235 continue;1243 continue;
1236 }1244 }
1237 }1245 }
test/run_tests.cpp+8-5
...@@ -202,7 +202,7 @@ static TestCase *add_parseh_case(const char *case_name, AllowWarnings allow_warn...@@ -202,7 +202,7 @@ static TestCase *add_parseh_case(const char *case_name, AllowWarnings allow_warn
202202
203 test_case->compiler_args.append("parseh");203 test_case->compiler_args.append("parseh");
204 test_case->compiler_args.append(tmp_h_path);204 test_case->compiler_args.append(tmp_h_path);
205 test_case->compiler_args.append("--verbose");205 //test_case->compiler_args.append("--verbose");
206206
207 test_cases.append(test_case);207 test_cases.append(test_case);
208208
...@@ -1883,11 +1883,14 @@ Foo fun(Foo *a);...@@ -1883,11 +1883,14 @@ Foo fun(Foo *a);
1883 R"SOURCE(1883 R"SOURCE(
1884extern void (*fn_ptr)(void);1884extern void (*fn_ptr)(void);
1885#define foo fn_ptr1885#define foo fn_ptr
1886 )SOURCE", 2,1886
1887extern char (*fn_ptr2)(int, float);
1888#define bar fn_ptr2
1889 )SOURCE", 4,
1887 "pub extern var fn_ptr: ?extern fn();",1890 "pub extern var fn_ptr: ?extern fn();",
1888 R"SOURCE(pub inline fn foo() {1891 "pub fn foo();",
1889 (??fn_ptr)();1892 "pub extern var fn_ptr2: ?extern fn(c_int, f32) -> u8;",
1890})SOURCE");1893 "pub fn bar(arg0: c_int, arg1: f32) -> u8;");
18911894
18921895
1893 add_parseh_case("#define string", AllowWarningsNo, R"SOURCE(1896 add_parseh_case("#define string", AllowWarningsNo, R"SOURCE(