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