| ... | @@ -2361,29 +2361,32 @@ fn store(cg: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerErr | ... | @@ -2361,29 +2361,32 @@ fn store(cg: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerErr |
| 2361 | .error_union => { | 2361 | .error_union => { |
| 2362 | const pl_ty = ty.errorUnionPayload(zcu); | 2362 | const pl_ty = ty.errorUnionPayload(zcu); |
| 2363 | if (!pl_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | 2363 | if (!pl_ty.hasRuntimeBitsIgnoreComptime(zcu)) { |
| 2364 | return cg.store(lhs, rhs, Type.anyerror, 0); | 2364 | return cg.store(lhs, rhs, Type.anyerror, offset); |
| 2365 | } | 2365 | } |
| 2366 | | 2366 | |
| 2367 | const len = @as(u32, @intCast(abi_size)); | 2367 | const len = @as(u32, @intCast(abi_size)); |
| | 2368 | assert(offset == 0); |
| 2368 | return cg.memcpy(lhs, rhs, .{ .imm32 = len }); | 2369 | return cg.memcpy(lhs, rhs, .{ .imm32 = len }); |
| 2369 | }, | 2370 | }, |
| 2370 | .optional => { | 2371 | .optional => { |
| 2371 | if (ty.isPtrLikeOptional(zcu)) { | 2372 | if (ty.isPtrLikeOptional(zcu)) { |
| 2372 | return cg.store(lhs, rhs, Type.usize, 0); | 2373 | return cg.store(lhs, rhs, Type.usize, offset); |
| 2373 | } | 2374 | } |
| 2374 | const pl_ty = ty.optionalChild(zcu); | 2375 | const pl_ty = ty.optionalChild(zcu); |
| 2375 | if (!pl_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | 2376 | if (!pl_ty.hasRuntimeBitsIgnoreComptime(zcu)) { |
| 2376 | return cg.store(lhs, rhs, Type.u8, 0); | 2377 | return cg.store(lhs, rhs, Type.u8, offset); |
| 2377 | } | 2378 | } |
| 2378 | if (pl_ty.zigTypeTag(zcu) == .error_set) { | 2379 | if (pl_ty.zigTypeTag(zcu) == .error_set) { |
| 2379 | return cg.store(lhs, rhs, Type.anyerror, 0); | 2380 | return cg.store(lhs, rhs, Type.anyerror, offset); |
| 2380 | } | 2381 | } |
| 2381 | | 2382 | |
| 2382 | const len = @as(u32, @intCast(abi_size)); | 2383 | const len = @as(u32, @intCast(abi_size)); |
| | 2384 | assert(offset == 0); |
| 2383 | return cg.memcpy(lhs, rhs, .{ .imm32 = len }); | 2385 | return cg.memcpy(lhs, rhs, .{ .imm32 = len }); |
| 2384 | }, | 2386 | }, |
| 2385 | .@"struct", .array, .@"union" => if (isByRef(ty, zcu, cg.target)) { | 2387 | .@"struct", .array, .@"union" => if (isByRef(ty, zcu, cg.target)) { |
| 2386 | const len = @as(u32, @intCast(abi_size)); | 2388 | const len = @as(u32, @intCast(abi_size)); |
| | 2389 | assert(offset == 0); |
| 2387 | return cg.memcpy(lhs, rhs, .{ .imm32 = len }); | 2390 | return cg.memcpy(lhs, rhs, .{ .imm32 = len }); |
| 2388 | }, | 2391 | }, |
| 2389 | .vector => switch (determineSimdStoreStrategy(ty, zcu, cg.target)) { | 2392 | .vector => switch (determineSimdStoreStrategy(ty, zcu, cg.target)) { |
| ... | @@ -2407,6 +2410,7 @@ fn store(cg: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerErr | ... | @@ -2407,6 +2410,7 @@ fn store(cg: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerErr |
| 2407 | }, | 2410 | }, |
| 2408 | .pointer => { | 2411 | .pointer => { |
| 2409 | if (ty.isSlice(zcu)) { | 2412 | if (ty.isSlice(zcu)) { |
| | 2413 | assert(offset == 0); |
| 2410 | // store pointer first | 2414 | // store pointer first |
| 2411 | // lower it to the stack so we do not have to store rhs into a local first | 2415 | // lower it to the stack so we do not have to store rhs into a local first |
| 2412 | try cg.emitWValue(lhs); | 2416 | try cg.emitWValue(lhs); |
| ... | @@ -2421,6 +2425,7 @@ fn store(cg: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerErr | ... | @@ -2421,6 +2425,7 @@ fn store(cg: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerErr |
| 2421 | } | 2425 | } |
| 2422 | }, | 2426 | }, |
| 2423 | .int, .@"enum", .float => if (abi_size > 8 and abi_size <= 16) { | 2427 | .int, .@"enum", .float => if (abi_size > 8 and abi_size <= 16) { |
| | 2428 | assert(offset == 0); |
| 2424 | try cg.emitWValue(lhs); | 2429 | try cg.emitWValue(lhs); |
| 2425 | const lsb = try cg.load(rhs, Type.u64, 0); | 2430 | const lsb = try cg.load(rhs, Type.u64, 0); |
| 2426 | try cg.store(.stack, lsb, Type.u64, 0 + lhs.offset()); | 2431 | try cg.store(.stack, lsb, Type.u64, 0 + lhs.offset()); |
| ... | @@ -2430,6 +2435,7 @@ fn store(cg: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerErr | ... | @@ -2430,6 +2435,7 @@ fn store(cg: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerErr |
| 2430 | try cg.store(.stack, msb, Type.u64, 8 + lhs.offset()); | 2435 | try cg.store(.stack, msb, Type.u64, 8 + lhs.offset()); |
| 2431 | return; | 2436 | return; |
| 2432 | } else if (abi_size > 16) { | 2437 | } else if (abi_size > 16) { |
| | 2438 | assert(offset == 0); |
| 2433 | try cg.memcpy(lhs, rhs, .{ .imm32 = @as(u32, @intCast(ty.abiSize(zcu))) }); | 2439 | try cg.memcpy(lhs, rhs, .{ .imm32 = @as(u32, @intCast(ty.abiSize(zcu))) }); |
| 2434 | }, | 2440 | }, |
| 2435 | else => if (abi_size > 8) { | 2441 | else => if (abi_size > 8) { |
| ... | @@ -4438,9 +4444,6 @@ fn airOptionalPayloadPtrSet(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void | ... | @@ -4438,9 +4444,6 @@ fn airOptionalPayloadPtrSet(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void |
| 4438 | const operand = try cg.resolveInst(ty_op.operand); | 4444 | const operand = try cg.resolveInst(ty_op.operand); |
| 4439 | const opt_ty = cg.typeOf(ty_op.operand).childType(zcu); | 4445 | const opt_ty = cg.typeOf(ty_op.operand).childType(zcu); |
| 4440 | const payload_ty = opt_ty.optionalChild(zcu); | 4446 | const payload_ty = opt_ty.optionalChild(zcu); |
| 4441 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | | |
| 4442 | return cg.fail("TODO: Implement OptionalPayloadPtrSet for optional with zero-sized type {}", .{payload_ty.fmtDebug()}); | | |
| 4443 | } | | |
| 4444 | | 4447 | |
| 4445 | if (opt_ty.optionalReprIsPayload(zcu)) { | 4448 | if (opt_ty.optionalReprIsPayload(zcu)) { |
| 4446 | return cg.finishAir(inst, operand, &.{ty_op.operand}); | 4449 | return cg.finishAir(inst, operand, &.{ty_op.operand}); |
| ... | @@ -5407,31 +5410,40 @@ fn cmpOptionals(cg: *CodeGen, lhs: WValue, rhs: WValue, operand_ty: Type, op: st | ... | @@ -5407,31 +5410,40 @@ fn cmpOptionals(cg: *CodeGen, lhs: WValue, rhs: WValue, operand_ty: Type, op: st |
| 5407 | assert(operand_ty.hasRuntimeBitsIgnoreComptime(zcu)); | 5410 | assert(operand_ty.hasRuntimeBitsIgnoreComptime(zcu)); |
| 5408 | assert(op == .eq or op == .neq); | 5411 | assert(op == .eq or op == .neq); |
| 5409 | const payload_ty = operand_ty.optionalChild(zcu); | 5412 | const payload_ty = operand_ty.optionalChild(zcu); |
| | 5413 | assert(!isByRef(payload_ty, zcu, cg.target)); |
| 5410 | | 5414 | |
| 5411 | // We store the final result in here that will be validated | 5415 | var result = try cg.allocLocal(Type.i32); |
| 5412 | // if the optional is truly equal. | | |
| 5413 | var result = try cg.ensureAllocLocal(Type.i32); | | |
| 5414 | defer result.free(cg); | 5416 | defer result.free(cg); |
| 5415 | | 5417 | |
| | 5418 | var lhs_null = try cg.allocLocal(Type.i32); |
| | 5419 | defer lhs_null.free(cg); |
| | 5420 | |
| 5416 | try cg.startBlock(.block, .empty); | 5421 | try cg.startBlock(.block, .empty); |
| | 5422 | |
| | 5423 | try cg.addImm32(if (op == .eq) 0 else 1); |
| | 5424 | try cg.addLocal(.local_set, result.local.value); |
| | 5425 | |
| 5417 | _ = try cg.isNull(lhs, operand_ty, .i32_eq); | 5426 | _ = try cg.isNull(lhs, operand_ty, .i32_eq); |
| | 5427 | try cg.addLocal(.local_tee, lhs_null.local.value); |
| 5418 | _ = try cg.isNull(rhs, operand_ty, .i32_eq); | 5428 | _ = try cg.isNull(rhs, operand_ty, .i32_eq); |
| 5419 | try cg.addTag(.i32_ne); // inverse so we can exit early | 5429 | try cg.addTag(.i32_ne); |
| 5420 | try cg.addLabel(.br_if, 0); | 5430 | try cg.addLabel(.br_if, 0); // only one is null |
| | 5431 | |
| | 5432 | try cg.addImm32(if (op == .eq) 1 else 0); |
| | 5433 | try cg.addLocal(.local_set, result.local.value); |
| | 5434 | |
| | 5435 | try cg.addLocal(.local_get, lhs_null.local.value); |
| | 5436 | try cg.addLabel(.br_if, 0); // both are null |
| 5421 | | 5437 | |
| 5422 | _ = try cg.load(lhs, payload_ty, 0); | 5438 | _ = try cg.load(lhs, payload_ty, 0); |
| 5423 | _ = try cg.load(rhs, payload_ty, 0); | 5439 | _ = try cg.load(rhs, payload_ty, 0); |
| 5424 | const opcode = buildOpcode(.{ .op = .ne, .valtype1 = typeToValtype(payload_ty, zcu, cg.target) }); | 5440 | _ = try cg.cmp(.stack, .stack, payload_ty, op); |
| 5425 | try cg.addTag(Mir.Inst.Tag.fromOpcode(opcode)); | | |
| 5426 | try cg.addLabel(.br_if, 0); | | |
| 5427 | | | |
| 5428 | try cg.addImm32(1); | | |
| 5429 | try cg.addLocal(.local_set, result.local.value); | 5441 | try cg.addLocal(.local_set, result.local.value); |
| | 5442 | |
| 5430 | try cg.endBlock(); | 5443 | try cg.endBlock(); |
| 5431 | | 5444 | |
| 5432 | try cg.emitWValue(result); | 5445 | try cg.addLocal(.local_get, result.local.value); |
| 5433 | try cg.addImm32(0); | 5446 | |
| 5434 | try cg.addTag(if (op == .eq) .i32_ne else .i32_eq); | | |
| 5435 | return .stack; | 5447 | return .stack; |
| 5436 | } | 5448 | } |
| 5437 | | 5449 | |