| author | |
| committer | |
| log | d7847053531c3352db8355e21e54b102958cbb8a |
| tree | b360eeecaa1b6624c268054bb2a7d79d4678d591 |
| parent | 76b1cbc2ea50be928608b80bdd8ab25cd1b964f3 |
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 | 193 | } |
| 194 | 194 | |
| 195 | 195 | ScopeFnDef *create_fndef_scope(AstNode *node, Scope *parent, FnTableEntry *fn_entry) { |
| 196 | assert(node->type == NodeTypeFnDef); | |
| 196 | assert(!node || node->type == NodeTypeFnDef); | |
| 197 | 197 | ScopeFnDef *scope = allocate<ScopeFnDef>(1); |
| 198 | 198 | init_scope(&scope->base, ScopeIdFnDef, node, parent); |
| 199 | 199 | scope->fn_entry = fn_entry; |
| ... | ... | @@ -2341,31 +2341,20 @@ bool type_is_codegen_pointer(TypeTableEntry *type) { |
| 2341 | 2341 | AstNode *get_param_decl_node(FnTableEntry *fn_entry, size_t index) { |
| 2342 | 2342 | if (fn_entry->param_source_nodes) |
| 2343 | 2343 | return fn_entry->param_source_nodes[index]; |
| 2344 | else | |
| 2344 | else if (fn_entry->proto_node) | |
| 2345 | 2345 | return fn_entry->proto_node->data.fn_proto.params.at(index); |
| 2346 | else | |
| 2347 | return nullptr; | |
| 2346 | 2348 | } |
| 2347 | 2349 | |
| 2348 | static void analyze_fn_body(CodeGen *g, FnTableEntry *fn_table_entry) { | |
| 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 | |
| 2350 | void define_local_param_variables(CodeGen *g, FnTableEntry *fn_table_entry, VariableTableEntry **arg_vars) { | |
| 2362 | 2351 | TypeTableEntry *fn_type = fn_table_entry->type_entry; |
| 2363 | 2352 | assert(!fn_type->data.fn.is_generic); |
| 2364 | 2353 | FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id; |
| 2365 | 2354 | for (size_t i = 0; i < fn_type_id->param_count; i += 1) { |
| 2366 | 2355 | FnTypeParamInfo *param_info = &fn_type_id->param_info[i]; |
| 2367 | 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); | |
| 2369 | 2358 | |
| 2370 | 2359 | TypeTableEntry *param_type = param_info->type; |
| 2371 | 2360 | bool is_noalias = param_info->is_noalias; |
| ... | ... | @@ -2380,7 +2369,7 @@ static void analyze_fn_body(CodeGen *g, FnTableEntry *fn_table_entry) { |
| 2380 | 2369 | } |
| 2381 | 2370 | |
| 2382 | 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 | 2373 | var->src_arg_index = i; |
| 2385 | 2374 | fn_table_entry->child_scope = var->child_scope; |
| 2386 | 2375 | |
| ... | ... | @@ -2391,30 +2380,20 @@ static void analyze_fn_body(CodeGen *g, FnTableEntry *fn_table_entry) { |
| 2391 | 2380 | if (fn_type->data.fn.gen_param_info) { |
| 2392 | 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; | |
| 2397 | 2383 | |
| 2398 | if (fn_type_id->is_extern && handle_is_ptr(expected_type)) { | |
| 2399 | add_node_error(g, fn_proto->return_type, | |
| 2400 | buf_sprintf("byvalue types not yet supported on extern function return values")); | |
| 2384 | if (arg_vars) { | |
| 2385 | arg_vars[i] = var; | |
| 2386 | } | |
| 2401 | 2387 | } |
| 2388 | } | |
| 2402 | 2389 | |
| 2403 | ir_gen_fn(g, fn_table_entry); | |
| 2404 | if (fn_table_entry->ir_executable.invalid) { | |
| 2405 | fn_table_entry->anal_state = FnAnalStateInvalid; | |
| 2406 | return; | |
| 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 | } | |
| 2390 | void analyze_fn_ir(CodeGen *g, FnTableEntry *fn_table_entry, AstNode *return_type_node) { | |
| 2391 | TypeTableEntry *fn_type = fn_table_entry->type_entry; | |
| 2392 | assert(!fn_type->data.fn.is_generic); | |
| 2393 | FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id; | |
| 2415 | 2394 | |
| 2416 | 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 | 2397 | fn_table_entry->implicit_return_type = block_return_type; |
| 2419 | 2398 | |
| 2420 | 2399 | if (block_return_type->id == TypeTableEntryIdInvalid || |
| ... | ... | @@ -2434,6 +2413,46 @@ static void analyze_fn_body(CodeGen *g, FnTableEntry *fn_table_entry) { |
| 2434 | 2413 | fn_table_entry->anal_state = FnAnalStateComplete; |
| 2435 | 2414 | } |
| 2436 | 2415 | |
| 2416 | static 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 | ||
| 2437 | 2456 | static void add_symbols_from_import(CodeGen *g, AstNode *dst_use_node) { |
| 2438 | 2457 | IrInstruction *use_target_value = dst_use_node->data.use.value; |
| 2439 | 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 | 83 | void eval_min_max_value(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val, bool is_max); |
| 84 | 84 | |
| 85 | 85 | void render_const_value(Buf *buf, ConstExprValue *const_val); |
| 86 | void define_local_param_variables(CodeGen *g, FnTableEntry *fn_table_entry, VariableTableEntry **arg_vars); | |
| 87 | void analyze_fn_ir(CodeGen *g, FnTableEntry *fn_table_entry, AstNode *return_type_node); | |
| 86 | 88 | |
| 87 | 89 | ScopeBlock *create_block_scope(AstNode *node, Scope *parent); |
| 88 | 90 | ScopeDefer *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 | 908 | if (param_info->is_noalias) { |
| 909 | 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 | 914 | if (fn_type_id->return_type->id == TypeTableEntryIdVoid) { |
| 914 | 915 | fprintf(ar->f, ");\n"); |
| ... | ... | @@ -947,24 +948,28 @@ static void ast_render_tld_var(AstRender *ar, Buf *name, TldVar *tld_var) { |
| 947 | 948 | if (type_entry->id == TypeTableEntryIdStruct) { |
| 948 | 949 | const char *extern_str = extern_string(type_entry->data.structure.is_extern); |
| 949 | 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 | TypeStructField *field = &type_entry->data.structure.fields[i]; | |
| 952 | fprintf(ar->f, " "); | |
| 953 | print_symbol(ar, field->name); | |
| 954 | fprintf(ar->f, ": %s,\n", buf_ptr(&field->type_entry->name)); | |
| 951 | if (type_entry->data.structure.complete) { | |
| 952 | for (size_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) { | |
| 953 | TypeStructField *field = &type_entry->data.structure.fields[i]; | |
| 954 | fprintf(ar->f, " "); | |
| 955 | print_symbol(ar, field->name); | |
| 956 | fprintf(ar->f, ": %s,\n", buf_ptr(&field->type_entry->name)); | |
| 957 | } | |
| 955 | 958 | } |
| 956 | 959 | fprintf(ar->f, "}"); |
| 957 | 960 | } else if (type_entry->id == TypeTableEntryIdEnum) { |
| 958 | 961 | const char *extern_str = extern_string(type_entry->data.enumeration.is_extern); |
| 959 | 962 | fprintf(ar->f, "%senum {\n", extern_str); |
| 960 | for (size_t i = 0; i < type_entry->data.enumeration.src_field_count; i += 1) { | |
| 961 | TypeEnumField *field = &type_entry->data.enumeration.fields[i]; | |
| 962 | fprintf(ar->f, " "); | |
| 963 | print_symbol(ar, field->name); | |
| 964 | if (field->type_entry->id == TypeTableEntryIdVoid) { | |
| 965 | fprintf(ar->f, ",\n"); | |
| 966 | } else { | |
| 967 | fprintf(ar->f, ": %s,\n", buf_ptr(&field->type_entry->name)); | |
| 963 | if (type_entry->data.enumeration.complete) { | |
| 964 | for (size_t i = 0; i < type_entry->data.enumeration.src_field_count; i += 1) { | |
| 965 | TypeEnumField *field = &type_entry->data.enumeration.fields[i]; | |
| 966 | fprintf(ar->f, " "); | |
| 967 | print_symbol(ar, field->name); | |
| 968 | if (field->type_entry->id == TypeTableEntryIdVoid) { | |
| 969 | fprintf(ar->f, ",\n"); | |
| 970 | } else { | |
| 971 | fprintf(ar->f, ": %s,\n", buf_ptr(&field->type_entry->name)); | |
| 972 | } | |
| 968 | 973 | } |
| 969 | 974 | } |
| 970 | 975 | fprintf(ar->f, "}"); |
src/codegen.cpp+10-5| ... | ... | @@ -287,6 +287,8 @@ static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) { |
| 287 | 287 | assert(scope->parent); |
| 288 | 288 | ScopeFnDef *fn_scope = (ScopeFnDef *)scope; |
| 289 | 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 | 292 | unsigned line_number = fn_table_entry->proto_node->line + 1; |
| 291 | 293 | unsigned scope_line = line_number; |
| 292 | 294 | bool is_definition = fn_table_entry->fn_def_node != nullptr; |
| ... | ... | @@ -2808,7 +2810,6 @@ static void do_code_gen(CodeGen *g) { |
| 2808 | 2810 | continue; |
| 2809 | 2811 | |
| 2810 | 2812 | assert(var->decl_node); |
| 2811 | assert(var->decl_node->type == NodeTypeVariableDeclaration); | |
| 2812 | 2813 | |
| 2813 | 2814 | LLVMValueRef global_value; |
| 2814 | 2815 | if (var->is_extern) { |
| ... | ... | @@ -3033,9 +3034,11 @@ static void do_code_gen(CodeGen *g) { |
| 3033 | 3034 | unsigned align_bytes = ZigLLVMGetPrefTypeAlignment(g->target_data_ref, var->value.type->type_ref); |
| 3034 | 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 | buf_ptr(&var->name), import->di_file, var->decl_node->line + 1, | |
| 3038 | gen_type->di_type, !g->strip_debug_symbols, 0, var->gen_arg_index + 1); | |
| 3037 | if (var->decl_node) { | |
| 3038 | var->di_loc_var = ZigLLVMCreateParameterVariable(g->dbuilder, get_di_scope(g, var->parent_scope), | |
| 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 | } | |
| 3039 | 3042 | |
| 3040 | 3043 | } |
| 3041 | 3044 | } |
| ... | ... | @@ -3062,7 +3065,9 @@ static void do_code_gen(CodeGen *g) { |
| 3062 | 3065 | LLVMBuildStore(g->builder, LLVMGetParam(fn, variable->gen_arg_index), variable->value_ref); |
| 3063 | 3066 | } |
| 3064 | 3067 | |
| 3065 | gen_var_debug_decl(g, variable); | |
| 3068 | if (variable->decl_node) { | |
| 3069 | gen_var_debug_decl(g, variable); | |
| 3070 | } | |
| 3066 | 3071 | } |
| 3067 | 3072 | |
| 3068 | 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 | 500 | |
| 501 | 501 | template<typename T> |
| 502 | 502 | static T *ir_build_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) { |
| 503 | assert(source_node); | |
| 504 | 503 | T *special_instruction = ir_create_instruction<T>(irb, scope, source_node); |
| 505 | 504 | ir_instruction_append(irb->current_basic_block, &special_instruction->base); |
| 506 | 505 | return special_instruction; |
| ... | ... | @@ -10120,7 +10119,7 @@ static TypeTableEntry *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruc |
| 10120 | 10119 | find_libc_include_path(ira->codegen); |
| 10121 | 10120 | |
| 10122 | 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 | 10123 | child_import->c_import_node = node; |
| 10125 | 10124 | |
| 10126 | 10125 | ZigList<ErrorMsg *> errors = {0}; |
| ... | ... | @@ -10143,7 +10142,7 @@ static TypeTableEntry *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruc |
| 10143 | 10142 | if (ira->codegen->verbose) { |
| 10144 | 10143 | fprintf(stderr, "\nC imports:\n"); |
| 10145 | 10144 | fprintf(stderr, "-----------\n"); |
| 10146 | ir_print_decls(stderr, child_import); | |
| 10145 | ast_render_decls(stderr, 4, child_import); | |
| 10147 | 10146 | } |
| 10148 | 10147 | |
| 10149 | 10148 | // 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 | 11545 | zig_unreachable(); |
| 11547 | 11546 | } |
| 11548 | 11547 | |
| 11548 | FnTableEntry *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 | 24 | bool ir_has_side_effects(IrInstruction *instruction); |
| 25 | 25 | ConstExprValue *const_ptr_pointee(ConstExprValue *const_val); |
| 26 | 26 | |
| 27 | FnTableEntry *ir_create_inline_fn(CodeGen *codegen, Buf *fn_name, VariableTableEntry *var, Scope *parent_scope); | |
| 28 | ||
| 27 | 29 | #endif |
src/ir_print.cpp-64| ... | ... | @@ -1093,67 +1093,3 @@ void ir_print(FILE *f, IrExecutable *executable, int indent_size) { |
| 1093 | 1093 | } |
| 1094 | 1094 | } |
| 1095 | 1095 | } |
| 1096 | ||
| 1097 | static 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 | ||
| 1112 | static 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 | ||
| 1116 | static 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 | ||
| 1120 | static 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 | ||
| 1124 | void 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 | 14 | |
| 15 | 15 | void ir_print(FILE *f, IrExecutable *executable, int indent_size); |
| 16 | 16 | |
| 17 | void ir_print_decls(FILE *f, ImportTableEntry *import); | |
| 18 | ||
| 19 | ||
| 20 | 17 | #endif |
src/parseh.cpp+16-8| ... | ... | @@ -5,14 +5,15 @@ |
| 5 | 5 | * See http://opensource.org/licenses/MIT |
| 6 | 6 | */ |
| 7 | 7 | |
| 8 | #include "parseh.hpp" | |
| 8 | #include "all_types.hpp" | |
| 9 | #include "analyze.hpp" | |
| 10 | #include "c_tokenizer.hpp" | |
| 9 | 11 | #include "config.h" |
| 10 | #include "os.hpp" | |
| 11 | 12 | #include "error.hpp" |
| 13 | #include "ir.hpp" | |
| 14 | #include "os.hpp" | |
| 15 | #include "parseh.hpp" | |
| 12 | 16 | #include "parser.hpp" |
| 13 | #include "all_types.hpp" | |
| 14 | #include "c_tokenizer.hpp" | |
| 15 | #include "analyze.hpp" | |
| 16 | 17 | |
| 17 | 18 | #include <clang/Frontend/ASTUnit.h> |
| 18 | 19 | #include <clang/Frontend/CompilerInstance.h> |
| ... | ... | @@ -133,6 +134,13 @@ static void parseh_init_tld(Context *c, Tld *tld, TldId id, Buf *name) { |
| 133 | 134 | tld->resolution = TldResolutionOk; |
| 134 | 135 | } |
| 135 | 136 | |
| 137 | static 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 | ||
| 136 | 144 | static TldVar *create_global_var(Context *c, Buf *name, ConstExprValue *var_value, bool is_const) { |
| 137 | 145 | auto entry = c->import->decls_scope->decl_table.maybe_get(name); |
| 138 | 146 | if (entry) { |
| ... | ... | @@ -143,6 +151,7 @@ static TldVar *create_global_var(Context *c, Buf *name, ConstExprValue *var_valu |
| 143 | 151 | TldVar *tld_var = allocate<TldVar>(1); |
| 144 | 152 | parseh_init_tld(c, &tld_var->base, TldIdVar, name); |
| 145 | 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 | 155 | return tld_var; |
| 147 | 156 | } |
| 148 | 157 | |
| ... | ... | @@ -1229,9 +1238,8 @@ static void process_symbol_macros(Context *c) { |
| 1229 | 1238 | if (var_type->id == TypeTableEntryIdMaybe && !tld_var->var->src_is_const) { |
| 1230 | 1239 | TypeTableEntry *child_type = var_type->data.maybe.child_type; |
| 1231 | 1240 | if (child_type->id == TypeTableEntryIdFn) { |
| 1232 | zig_panic("TODO macro alias of function pointer in .h file"); | |
| 1233 | //Tld *fn_tld = create_inline_fn_alias(c, ms.name, tld_var->var); | |
| 1234 | //c->macro_table.put(ms.name, fn_tld); | |
| 1241 | Tld *tld = create_inline_fn_tld(c, ms.name, tld_var); | |
| 1242 | c->macro_table.put(ms.name, tld); | |
| 1235 | 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 | 202 | |
| 203 | 203 | test_case->compiler_args.append("parseh"); |
| 204 | 204 | test_case->compiler_args.append(tmp_h_path); |
| 205 | test_case->compiler_args.append("--verbose"); | |
| 205 | //test_case->compiler_args.append("--verbose"); | |
| 206 | 206 | |
| 207 | 207 | test_cases.append(test_case); |
| 208 | 208 | |
| ... | ... | @@ -1883,11 +1883,14 @@ Foo fun(Foo *a); |
| 1883 | 1883 | R"SOURCE( |
| 1884 | 1884 | extern void (*fn_ptr)(void); |
| 1885 | 1885 | #define foo fn_ptr |
| 1886 | )SOURCE", 2, | |
| 1886 | ||
| 1887 | extern char (*fn_ptr2)(int, float); | |
| 1888 | #define bar fn_ptr2 | |
| 1889 | )SOURCE", 4, | |
| 1887 | 1890 | "pub extern var fn_ptr: ?extern fn();", |
| 1888 | R"SOURCE(pub inline fn foo() { | |
| 1889 | (??fn_ptr)(); | |
| 1890 | })SOURCE"); | |
| 1891 | "pub fn foo();", | |
| 1892 | "pub extern var fn_ptr2: ?extern fn(c_int, f32) -> u8;", | |
| 1893 | "pub fn bar(arg0: c_int, arg1: f32) -> u8;"); | |
| 1891 | 1894 | |
| 1892 | 1895 | |
| 1893 | 1896 | add_parseh_case("#define string", AllowWarningsNo, R"SOURCE( |