| ... | ... | @@ -2902,6 +2902,7 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool { |
| 2902 | 2902 | decl.generation = mod.generation; |
| 2903 | 2903 | return false; |
| 2904 | 2904 | } |
| 2905 | log.debug("semaDecl {*} ({s})", .{ decl, decl.name }); |
| 2905 | 2906 | |
| 2906 | 2907 | var block_scope: Scope.Block = .{ |
| 2907 | 2908 | .parent = null, |
| ... | ... | @@ -2938,106 +2939,109 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool { |
| 2938 | 2939 | const decl_arena_state = try decl_arena.allocator.create(std.heap.ArenaAllocator.State); |
| 2939 | 2940 | |
| 2940 | 2941 | if (decl_tv.val.castTag(.function)) |fn_payload| { |
| 2941 | | var prev_type_has_bits = false; |
| 2942 | | var prev_is_inline = false; |
| 2943 | | var type_changed = true; |
| 2944 | | |
| 2945 | | if (decl.has_tv) { |
| 2946 | | prev_type_has_bits = decl.ty.hasCodeGenBits(); |
| 2947 | | type_changed = !decl.ty.eql(decl_tv.ty); |
| 2948 | | if (decl.getFunction()) |prev_func| { |
| 2949 | | prev_is_inline = prev_func.state == .inline_only; |
| 2942 | const func = fn_payload.data; |
| 2943 | const owns_tv = func.owner_decl == decl; |
| 2944 | if (owns_tv) { |
| 2945 | var prev_type_has_bits = false; |
| 2946 | var prev_is_inline = false; |
| 2947 | var type_changed = true; |
| 2948 | |
| 2949 | if (decl.has_tv) { |
| 2950 | prev_type_has_bits = decl.ty.hasCodeGenBits(); |
| 2951 | type_changed = !decl.ty.eql(decl_tv.ty); |
| 2952 | if (decl.getFunction()) |prev_func| { |
| 2953 | prev_is_inline = prev_func.state == .inline_only; |
| 2954 | } |
| 2955 | decl.clearValues(gpa); |
| 2950 | 2956 | } |
| 2951 | | decl.clearValues(gpa); |
| 2952 | | } |
| 2953 | | |
| 2954 | | decl.ty = try decl_tv.ty.copy(&decl_arena.allocator); |
| 2955 | | decl.val = try decl_tv.val.copy(&decl_arena.allocator); |
| 2956 | | decl.align_val = try align_val.copy(&decl_arena.allocator); |
| 2957 | | decl.linksection_val = try linksection_val.copy(&decl_arena.allocator); |
| 2958 | | decl.has_tv = true; |
| 2959 | | decl.owns_tv = fn_payload.data.owner_decl == decl; |
| 2960 | | decl_arena_state.* = decl_arena.state; |
| 2961 | | decl.value_arena = decl_arena_state; |
| 2962 | | decl.analysis = .complete; |
| 2963 | | decl.generation = mod.generation; |
| 2964 | 2957 | |
| 2965 | | const is_inline = decl_tv.ty.fnCallingConvention() == .Inline; |
| 2966 | | if (!is_inline and decl_tv.ty.hasCodeGenBits()) { |
| 2967 | | // We don't fully codegen the decl until later, but we do need to reserve a global |
| 2968 | | // offset table index for it. This allows us to codegen decls out of dependency order, |
| 2969 | | // increasing how many computations can be done in parallel. |
| 2970 | | try mod.comp.bin_file.allocateDeclIndexes(decl); |
| 2971 | | try mod.comp.work_queue.writeItem(.{ .codegen_decl = decl }); |
| 2972 | | if (type_changed and mod.emit_h != null) { |
| 2973 | | try mod.comp.work_queue.writeItem(.{ .emit_h_decl = decl }); |
| 2958 | decl.ty = try decl_tv.ty.copy(&decl_arena.allocator); |
| 2959 | decl.val = try decl_tv.val.copy(&decl_arena.allocator); |
| 2960 | decl.align_val = try align_val.copy(&decl_arena.allocator); |
| 2961 | decl.linksection_val = try linksection_val.copy(&decl_arena.allocator); |
| 2962 | decl.has_tv = true; |
| 2963 | decl.owns_tv = owns_tv; |
| 2964 | decl_arena_state.* = decl_arena.state; |
| 2965 | decl.value_arena = decl_arena_state; |
| 2966 | decl.analysis = .complete; |
| 2967 | decl.generation = mod.generation; |
| 2968 | |
| 2969 | const is_inline = decl_tv.ty.fnCallingConvention() == .Inline; |
| 2970 | if (!is_inline and decl_tv.ty.hasCodeGenBits()) { |
| 2971 | // We don't fully codegen the decl until later, but we do need to reserve a global |
| 2972 | // offset table index for it. This allows us to codegen decls out of dependency order, |
| 2973 | // increasing how many computations can be done in parallel. |
| 2974 | try mod.comp.bin_file.allocateDeclIndexes(decl); |
| 2975 | try mod.comp.work_queue.writeItem(.{ .codegen_func = func }); |
| 2976 | if (type_changed and mod.emit_h != null) { |
| 2977 | try mod.comp.work_queue.writeItem(.{ .emit_h_decl = decl }); |
| 2978 | } |
| 2979 | } else if (!prev_is_inline and prev_type_has_bits) { |
| 2980 | mod.comp.bin_file.freeDecl(decl); |
| 2974 | 2981 | } |
| 2975 | | } else if (!prev_is_inline and prev_type_has_bits) { |
| 2976 | | mod.comp.bin_file.freeDecl(decl); |
| 2977 | | } |
| 2978 | 2982 | |
| 2979 | | if (decl.is_exported) { |
| 2980 | | const export_src = src; // TODO make this point at `export` token |
| 2981 | | if (is_inline) { |
| 2982 | | return mod.fail(&block_scope.base, export_src, "export of inline function", .{}); |
| 2983 | if (decl.is_exported) { |
| 2984 | const export_src = src; // TODO make this point at `export` token |
| 2985 | if (is_inline) { |
| 2986 | return mod.fail(&block_scope.base, export_src, "export of inline function", .{}); |
| 2987 | } |
| 2988 | // The scope needs to have the decl in it. |
| 2989 | try mod.analyzeExport(&block_scope.base, export_src, mem.spanZ(decl.name), decl); |
| 2983 | 2990 | } |
| 2984 | | // The scope needs to have the decl in it. |
| 2985 | | try mod.analyzeExport(&block_scope.base, export_src, mem.spanZ(decl.name), decl); |
| 2986 | | } |
| 2987 | | return type_changed or is_inline != prev_is_inline; |
| 2988 | | } else { |
| 2989 | | var type_changed = true; |
| 2990 | | if (decl.has_tv) { |
| 2991 | | type_changed = !decl.ty.eql(decl_tv.ty); |
| 2992 | | decl.clearValues(gpa); |
| 2991 | return type_changed or is_inline != prev_is_inline; |
| 2993 | 2992 | } |
| 2993 | } |
| 2994 | var type_changed = true; |
| 2995 | if (decl.has_tv) { |
| 2996 | type_changed = !decl.ty.eql(decl_tv.ty); |
| 2997 | decl.clearValues(gpa); |
| 2998 | } |
| 2994 | 2999 | |
| 2995 | | decl.owns_tv = false; |
| 2996 | | var queue_linker_work = false; |
| 2997 | | if (decl_tv.val.castTag(.variable)) |payload| { |
| 2998 | | const variable = payload.data; |
| 2999 | | if (variable.owner_decl == decl) { |
| 3000 | | decl.owns_tv = true; |
| 3001 | | queue_linker_work = true; |
| 3000 | decl.owns_tv = false; |
| 3001 | var queue_linker_work = false; |
| 3002 | if (decl_tv.val.castTag(.variable)) |payload| { |
| 3003 | const variable = payload.data; |
| 3004 | if (variable.owner_decl == decl) { |
| 3005 | decl.owns_tv = true; |
| 3006 | queue_linker_work = true; |
| 3002 | 3007 | |
| 3003 | | const copied_init = try variable.init.copy(&decl_arena.allocator); |
| 3004 | | variable.init = copied_init; |
| 3005 | | } |
| 3006 | | } else if (decl_tv.val.castTag(.extern_fn)) |payload| { |
| 3007 | | const owner_decl = payload.data; |
| 3008 | | if (decl == owner_decl) { |
| 3009 | | decl.owns_tv = true; |
| 3010 | | queue_linker_work = true; |
| 3011 | | } |
| 3008 | const copied_init = try variable.init.copy(&decl_arena.allocator); |
| 3009 | variable.init = copied_init; |
| 3012 | 3010 | } |
| 3011 | } else if (decl_tv.val.castTag(.extern_fn)) |payload| { |
| 3012 | const owner_decl = payload.data; |
| 3013 | if (decl == owner_decl) { |
| 3014 | decl.owns_tv = true; |
| 3015 | queue_linker_work = true; |
| 3016 | } |
| 3017 | } |
| 3013 | 3018 | |
| 3014 | | decl.ty = try decl_tv.ty.copy(&decl_arena.allocator); |
| 3015 | | decl.val = try decl_tv.val.copy(&decl_arena.allocator); |
| 3016 | | decl.align_val = try align_val.copy(&decl_arena.allocator); |
| 3017 | | decl.linksection_val = try linksection_val.copy(&decl_arena.allocator); |
| 3018 | | decl.has_tv = true; |
| 3019 | | decl_arena_state.* = decl_arena.state; |
| 3020 | | decl.value_arena = decl_arena_state; |
| 3021 | | decl.analysis = .complete; |
| 3022 | | decl.generation = mod.generation; |
| 3023 | | |
| 3024 | | if (queue_linker_work and decl.ty.hasCodeGenBits()) { |
| 3025 | | try mod.comp.bin_file.allocateDeclIndexes(decl); |
| 3026 | | try mod.comp.work_queue.writeItem(.{ .codegen_decl = decl }); |
| 3019 | decl.ty = try decl_tv.ty.copy(&decl_arena.allocator); |
| 3020 | decl.val = try decl_tv.val.copy(&decl_arena.allocator); |
| 3021 | decl.align_val = try align_val.copy(&decl_arena.allocator); |
| 3022 | decl.linksection_val = try linksection_val.copy(&decl_arena.allocator); |
| 3023 | decl.has_tv = true; |
| 3024 | decl_arena_state.* = decl_arena.state; |
| 3025 | decl.value_arena = decl_arena_state; |
| 3026 | decl.analysis = .complete; |
| 3027 | decl.generation = mod.generation; |
| 3027 | 3028 | |
| 3028 | | if (type_changed and mod.emit_h != null) { |
| 3029 | | try mod.comp.work_queue.writeItem(.{ .emit_h_decl = decl }); |
| 3030 | | } |
| 3031 | | } |
| 3029 | if (queue_linker_work and decl.ty.hasCodeGenBits()) { |
| 3030 | try mod.comp.bin_file.allocateDeclIndexes(decl); |
| 3031 | try mod.comp.work_queue.writeItem(.{ .codegen_decl = decl }); |
| 3032 | 3032 | |
| 3033 | | if (decl.is_exported) { |
| 3034 | | const export_src = src; // TODO point to the export token |
| 3035 | | // The scope needs to have the decl in it. |
| 3036 | | try mod.analyzeExport(&block_scope.base, export_src, mem.spanZ(decl.name), decl); |
| 3033 | if (type_changed and mod.emit_h != null) { |
| 3034 | try mod.comp.work_queue.writeItem(.{ .emit_h_decl = decl }); |
| 3037 | 3035 | } |
| 3036 | } |
| 3038 | 3037 | |
| 3039 | | return type_changed; |
| 3038 | if (decl.is_exported) { |
| 3039 | const export_src = src; // TODO point to the export token |
| 3040 | // The scope needs to have the decl in it. |
| 3041 | try mod.analyzeExport(&block_scope.base, export_src, mem.spanZ(decl.name), decl); |
| 3040 | 3042 | } |
| 3043 | |
| 3044 | return type_changed; |
| 3041 | 3045 | } |
| 3042 | 3046 | |
| 3043 | 3047 | /// Returns the depender's index of the dependee. |