| ... | ... | @@ -3247,22 +3247,31 @@ fn zirStoreToBlockPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE |
| 3247 | 3247 | defer tracy.end(); |
| 3248 | 3248 | |
| 3249 | 3249 | const bin_inst = sema.code.instructions.items(.data)[inst].bin; |
| 3250 | | const ptr = sema.inst_map.get(@enumToInt(bin_inst.lhs) - @as(u32, Zir.Inst.Ref.typed_value_map.len)) orelse { |
| 3250 | const ptr = sema.inst_map.get(Zir.refToIndex(bin_inst.lhs).?) orelse { |
| 3251 | 3251 | // This is an elided instruction, but AstGen was unable to omit it. |
| 3252 | 3252 | return; |
| 3253 | 3253 | }; |
| 3254 | | const value = sema.resolveInst(bin_inst.rhs); |
| 3255 | | const ptr_ty = try Type.ptr(sema.arena, .{ |
| 3256 | | .pointee_type = sema.typeOf(value), |
| 3257 | | // TODO figure out which address space is appropriate here |
| 3258 | | .@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .local), |
| 3259 | | }); |
| 3260 | | // TODO detect when this store should be done at compile-time. For example, |
| 3261 | | // if expressions should force it when the condition is compile-time known. |
| 3262 | | const src: LazySrcLoc = .unneeded; |
| 3263 | | try sema.requireRuntimeBlock(block, src); |
| 3264 | | const bitcasted_ptr = try block.addBitCast(ptr_ty, ptr); |
| 3265 | | return sema.storePtr(block, src, bitcasted_ptr, value); |
| 3254 | const operand = sema.resolveInst(bin_inst.rhs); |
| 3255 | const src: LazySrcLoc = sema.src; |
| 3256 | blk: { |
| 3257 | const ptr_inst = Air.refToIndex(ptr) orelse break :blk; |
| 3258 | if (sema.air_instructions.items(.tag)[ptr_inst] != .constant) break :blk; |
| 3259 | const air_datas = sema.air_instructions.items(.data); |
| 3260 | const ptr_val = sema.air_values.items[air_datas[ptr_inst].ty_pl.payload]; |
| 3261 | switch (ptr_val.tag()) { |
| 3262 | .inferred_alloc_comptime => { |
| 3263 | const iac = ptr_val.castTag(.inferred_alloc_comptime).?; |
| 3264 | return sema.storeToInferredAllocComptime(block, src, operand, iac); |
| 3265 | }, |
| 3266 | .inferred_alloc => { |
| 3267 | const inferred_alloc = ptr_val.castTag(.inferred_alloc).?; |
| 3268 | return sema.storeToInferredAlloc(block, src, ptr, operand, inferred_alloc); |
| 3269 | }, |
| 3270 | else => break :blk, |
| 3271 | } |
| 3272 | } |
| 3273 | |
| 3274 | return sema.storePtr(block, src, ptr, operand); |
| 3266 | 3275 | } |
| 3267 | 3276 | |
| 3268 | 3277 | fn zirStoreToInferredPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { |
| ... | ... | @@ -3273,46 +3282,71 @@ fn zirStoreToInferredPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compi |
| 3273 | 3282 | const bin_inst = sema.code.instructions.items(.data)[inst].bin; |
| 3274 | 3283 | const ptr = sema.resolveInst(bin_inst.lhs); |
| 3275 | 3284 | const operand = sema.resolveInst(bin_inst.rhs); |
| 3276 | | const operand_ty = sema.typeOf(operand); |
| 3277 | 3285 | const ptr_inst = Air.refToIndex(ptr).?; |
| 3278 | 3286 | assert(sema.air_instructions.items(.tag)[ptr_inst] == .constant); |
| 3279 | 3287 | const air_datas = sema.air_instructions.items(.data); |
| 3280 | 3288 | const ptr_val = sema.air_values.items[air_datas[ptr_inst].ty_pl.payload]; |
| 3281 | 3289 | |
| 3282 | | if (ptr_val.castTag(.inferred_alloc_comptime)) |iac| { |
| 3283 | | // There will be only one store_to_inferred_ptr because we are running at comptime. |
| 3284 | | // The alloc will turn into a Decl. |
| 3285 | | if (try sema.resolveMaybeUndefValAllowVariables(block, src, operand)) |operand_val| { |
| 3286 | | if (operand_val.tag() == .variable) { |
| 3287 | | return sema.failWithNeededComptime(block, src); |
| 3288 | | } |
| 3289 | | var anon_decl = try block.startAnonDecl(src); |
| 3290 | | defer anon_decl.deinit(); |
| 3291 | | iac.data.decl = try anon_decl.finish( |
| 3292 | | try operand_ty.copy(anon_decl.arena()), |
| 3293 | | try operand_val.copy(anon_decl.arena()), |
| 3294 | | ); |
| 3295 | | // TODO set the alignment on the decl |
| 3296 | | return; |
| 3297 | | } else { |
| 3298 | | return sema.failWithNeededComptime(block, src); |
| 3299 | | } |
| 3290 | switch (ptr_val.tag()) { |
| 3291 | .inferred_alloc_comptime => { |
| 3292 | const iac = ptr_val.castTag(.inferred_alloc_comptime).?; |
| 3293 | return sema.storeToInferredAllocComptime(block, src, operand, iac); |
| 3294 | }, |
| 3295 | .inferred_alloc => { |
| 3296 | const inferred_alloc = ptr_val.castTag(.inferred_alloc).?; |
| 3297 | return sema.storeToInferredAlloc(block, src, ptr, operand, inferred_alloc); |
| 3298 | }, |
| 3299 | else => unreachable, |
| 3300 | 3300 | } |
| 3301 | } |
| 3301 | 3302 | |
| 3302 | | if (ptr_val.castTag(.inferred_alloc)) |inferred_alloc| { |
| 3303 | | // Add the stored instruction to the set we will use to resolve peer types |
| 3304 | | // for the inferred allocation. |
| 3305 | | try inferred_alloc.data.stored_inst_list.append(sema.arena, operand); |
| 3306 | | // Create a runtime bitcast instruction with exactly the type the pointer wants. |
| 3307 | | const ptr_ty = try Type.ptr(sema.arena, .{ |
| 3308 | | .pointee_type = operand_ty, |
| 3309 | | .@"align" = inferred_alloc.data.alignment, |
| 3310 | | .@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .local), |
| 3311 | | }); |
| 3312 | | const bitcasted_ptr = try block.addBitCast(ptr_ty, ptr); |
| 3313 | | return sema.storePtr(block, src, bitcasted_ptr, operand); |
| 3303 | fn storeToInferredAlloc( |
| 3304 | sema: *Sema, |
| 3305 | block: *Block, |
| 3306 | src: LazySrcLoc, |
| 3307 | ptr: Air.Inst.Ref, |
| 3308 | operand: Air.Inst.Ref, |
| 3309 | inferred_alloc: *Value.Payload.InferredAlloc, |
| 3310 | ) CompileError!void { |
| 3311 | const operand_ty = sema.typeOf(operand); |
| 3312 | // Add the stored instruction to the set we will use to resolve peer types |
| 3313 | // for the inferred allocation. |
| 3314 | try inferred_alloc.data.stored_inst_list.append(sema.arena, operand); |
| 3315 | // Create a runtime bitcast instruction with exactly the type the pointer wants. |
| 3316 | const ptr_ty = try Type.ptr(sema.arena, .{ |
| 3317 | .pointee_type = operand_ty, |
| 3318 | .@"align" = inferred_alloc.data.alignment, |
| 3319 | .@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .local), |
| 3320 | }); |
| 3321 | const bitcasted_ptr = try block.addBitCast(ptr_ty, ptr); |
| 3322 | return sema.storePtr(block, src, bitcasted_ptr, operand); |
| 3323 | } |
| 3324 | |
| 3325 | fn storeToInferredAllocComptime( |
| 3326 | sema: *Sema, |
| 3327 | block: *Block, |
| 3328 | src: LazySrcLoc, |
| 3329 | operand: Air.Inst.Ref, |
| 3330 | iac: *Value.Payload.InferredAllocComptime, |
| 3331 | ) CompileError!void { |
| 3332 | const operand_ty = sema.typeOf(operand); |
| 3333 | // There will be only one store_to_inferred_ptr because we are running at comptime. |
| 3334 | // The alloc will turn into a Decl. |
| 3335 | if (try sema.resolveMaybeUndefValAllowVariables(block, src, operand)) |operand_val| { |
| 3336 | if (operand_val.tag() == .variable) { |
| 3337 | return sema.failWithNeededComptime(block, src); |
| 3338 | } |
| 3339 | var anon_decl = try block.startAnonDecl(src); |
| 3340 | defer anon_decl.deinit(); |
| 3341 | iac.data.decl = try anon_decl.finish( |
| 3342 | try operand_ty.copy(anon_decl.arena()), |
| 3343 | try operand_val.copy(anon_decl.arena()), |
| 3344 | ); |
| 3345 | // TODO set the alignment on the decl |
| 3346 | return; |
| 3347 | } else { |
| 3348 | return sema.failWithNeededComptime(block, src); |
| 3314 | 3349 | } |
| 3315 | | unreachable; |
| 3316 | 3350 | } |
| 3317 | 3351 | |
| 3318 | 3352 | fn zirSetEvalBranchQuota(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { |